diff --git a/FLUID_APACIGUAR_PLAN.md b/FLUID_APACIGUAR_PLAN.md new file mode 100644 index 0000000..d57ff4c --- /dev/null +++ b/FLUID_APACIGUAR_PLAN.md @@ -0,0 +1,143 @@ +# Plan para "Apaciguar" el Efecto Fluid sobre Textos + +## Comportamiento Actual +- El efecto de fluid responde al movimiento del mouse en toda la página (gracias a EventListener en document) +- Cuando el mouse está sobre texto, el efecto es tan intenso que dificulta la lectura +- La dinámica del efecto (color transition, fuerza, etc.) sigue funcionando bien + +## Objetivo +"Apaciguar" el efecto cuando el mouse está sobre áreas de texto - reducir su impacto visual sin eliminar la interacción. + +## Opciones viables: + +### Opción 1: Reducir intensidad basado en elementos (Recomendado) +**Enfoque:** Detectar cuándo el mouse está sobre elementos de texto/lectura y reducir la intensidad + +#### Implementación: +```javascript +// En fluid.js, modificar el event listener +document.addEventListener("mousemove", function(e) { + //Verificar si está sobre elementos que no deben tener efecto fuerte + const overText = isMouseOverTextElements(e.target); + + if (overText) { + //Modo "apaciguado" - reducir intensidad + pointers[0].dx = (e.clientX - canvas.offsetLeft - pointers[0].x) * 2.0; //Reducido (<10.0) + pointers[0].dy = (e.clientY - canvas.offsetTop - pointers[0].y) * 2.0; + + //Opcional: reducir el color también + const mutedColor = [colorArr[0]*0.7, colorArr[1]*0.7, colorArr[2]*0.7]; + pointers[0].color = mutedColor; + } else { + //Modo normal - comportamiento actual + pointers[0].dx = (e.clientX - canvas.offsetLeft - pointers[0].x) * 10.0; + pointers[0].dy = (e.clientY - canvas.offsetTop - pointers[0].y) * 10.0; + pointers[0].color = colorArr; + } + + pointers[0].x = e.clientX - canvas.offsetLeft; + pointers[0].y = e.clientY - canvas.offsetTop; +}); + +function isMouseOverTextElements(target) { + //Listar selectores de elementos donde NO queremos efecto fuerte + const textSelectors = [ + 'p', '.hero-content p','h1', '.hero-content h1', + 'h2', 'h3', 'a.sheet-link', '.sheet-link span', + '.menu-btn', '.eyebrow' + ]; + + for (const selector of textSelectors) { + if (target.closest(selector)) { + return true; + } + } + return false; +} +``` + +**Ventajas:** +- Automático y contextual +- No cambia la dinámica original en áreas no-textuales +- Conserva completa interacción +- Personalizable qué elementos "apacigar" + +--- + +### Opción 2: Transparencia condicional (Alternativa simple) +**Enfoque:** Reducir opacidad del canvas cuando está sobre texto + +#### Implementación: +```css +/* En styles.css */ +p, h1, h2, h3, +.sheet-link span, +.eyebrow { + position: relative; +} + +p::after, h1::after, h2::after, h3::after, +.sheet-link span::after, +.eyebrow::after { + content: ''; + position: absolute; + top: -10px; right: -10px; bottom: -10px; left: -10px; + z-index: 2; +} +``` + +**Ventajas:** +- Solución CSS-only (no requiere JS) +- Simple implementación + +**Desventajas:** +- No control fino, solo todo o nada +- Puede afectar capas y layout existing + +--- + +### Opción 3: Efecto "follow" más suave para texto +**Enfoque:** Reducir la intensidad (dx/dy multiplier) pero mantener color full + +#### Implementación: +```javascript +document.addEventListener("mousemove", function(e) { + const isOverReadableText = /(p|h[1-6]|.eyebrow|.sheet-link)/i.test(e.target.className || e.target.tagName); + + const multiplier = isOverReadableText ? 3.0 : 10.0; // Reducido de 10 a 3 sobre texto + + pointers[0].dx = (e.clientX - canvas.offsetLeft - pointers[0].x) * multiplier; + pointers[0].dy = (e.clientY - canvas.offsetTop - pointers[0].y) * multiplier; + //Restante del código... +}); +``` + +**Ventajas:** +- Muy sutil, difícil de notas +- Conserva dinámica del efecto + +--- + +## Recomendación Final: Implementar Opción 1 con refinamientos + +### Cambios específicos: +1. **En fluid.js** (líneas ~372): + - Modificar el `mousemove` handler para detectar elementos de texto + - Aplicar multiplicador reducido (*2 o *3) y color más tenue en esos casos + +2. **Lista de selectores** para "modo apaciguado": + ```javascript + ['p', 'h1', 'h2', 'h3', '.hero-content h1', '.eyebrow', + 'a.sheet-link', '.sheet-link span', '.menu-btn'] + ``` + +### Beneficios clave: +- 📖 Facilita la lectura al reducir ruido visual sobre texto +- ✨ Conserva el efecto completo en áreas no-textuales (fondo, logos) +- 🎨 Mantiene las transiciones de color entre marcas +- 🚀 Sin cambios en la dinámica del sistema fluid (solo intensidad) + +### Prueba y ajuste: +- Probar con diferentes multiplicadores (2.0 vs 3.0) para encontrar el balance ideal +- Ajustar selectores CSS según qué elementos necesitan "apaciguamiento" +- Verificar que botones/menu sigan siendo interactivos \ No newline at end of file diff --git a/FLUID_EFFECT_ANALYSIS.md b/FLUID_EFFECT_ANALYSIS.md new file mode 100644 index 0000000..e724cc4 --- /dev/null +++ b/FLUID_EFFECT_ANALYSIS.md @@ -0,0 +1,69 @@ +# Fluid Effect Debugging Analysis + +## Problem Statement +The fluid effect (WebGL canvas with mouse interaction) was not working properly over text areas and other HTML elements on the page. + +## Root Cause Analysis + +### How Canvas Events Work +Canvas elements only capture mouse events when: +1. The mouse pointer is directly over the canvas element itself, OR +2. The canvas has `pointer-events: none` CSS property (allowing events to pass through), OR +3. Event listeners are attached at a higher level (document/body) and manually checked for intersection with canvas bounds. + +### Current Implementation Issue +```javascript +// OLD CODE -only works when mouse is over canvas +canvas.addEventListener("mousemove", function(e) { + // Uses e.offsetX and e.offsetY - only available on canvas element +}); +``` + +### Expected Behavior +The fluid effect should respond to mouse movement anywhere on the page, including over text elements. + +## Solution Implemented + +### Key Changes Made in `fluid.js`: + +1. **Changed event listener target** from canvas to document: + ```javascript + // NEW CODE - works globally + document.addEventListener("mousemove", function(e) { + // Manually calculate position relative to canvas + }); + ``` + +2. **Updated coordinate calculation** to account for canvas position: + ```javascript + // OLD: Uses offsetX/Y (canvas-relative) + pointers[0].dx = (e.offsetX - pointers[0].x) * 10.0; + + // NEW: Uses clientX/Y plus manual canvas positioning + pointers[0].x = e.clientX - canvas.offsetLeft; + pointers[0].y = e.clientY - canvas.offsetTop; + ``` + +## Verification Steps + +After implementing the fix, verify that: +1. ✅ Fluid effect works when mouse is over the background/text areas +2. ✅ Color transitions between brand colors still function correctly +3. ✅ No JavaScript errors in browser console +4. ✅ Mobile touch events continue to work (already implemented) + +## Files Modified +- `fluid.js:372-395` - Updated mousemove event listener + +## Technical Details + +### Event Propagation Model +The solution leverages event bubbling: +1. Mouse move events bubble up from target element to document root +2. By attaching the listener at the `document` level, we capture ALL mouse movements +3. We manually check if coordinates intersect with canvas bounds (via canvas.offsetLeft/Top) + +### Coordinate Transformation +- `clientX/clientY`: Absolute page coordinates +- `canvas.offsetLeft/canvas.offsetTop`: Canvas position relative to viewport +- Result: Accurate positioning within canvas regardless of mouse location on page \ No newline at end of file diff --git a/fluid.js b/fluid.js index 4d1e2dd..ffcb786 100644 --- a/fluid.js +++ b/fluid.js @@ -368,9 +368,29 @@ function lerpColor(colorA, colorB, t) { let colorArr = currentColor; let count = 0; +// ===== DETECTAR ELEMENTOS DE TEXTO ===== +function isMouseOverTextElement(target) { + // Listado de selectores que necesitan "modo apaciguado" + const textSelectors = [ + 'p', '.hero-content p','h1', 'h2', 'h3', 'h4', 'h5', '.hero-content h1', + '.hero-content h2', '.eyebrow', 'a.sheet-link', '.sheet-link span', + '.menu-btn', '.sheet-link-desc', '.sheet-link-main' + ]; + + // Verificar si el target o sus ancestros coinciden con algún selector + for (const selector of textSelectors) { + if (target.closest(selector)) { + return true; + } + } + return false; +} + // ===== EVENTOS CON COLORES DE MARCA ===== -canvas.addEventListener("mousemove", function (e) { - console.log("Mouse moviéndose:", e.clientX, e.clientY); +document.addEventListener("mousemove", function (e) { + // Detectar si estamos sobre un elemento de texto + const overText = isMouseOverTextElement(e.target); + count++; if (count > 1) { transitionProgress += transitionSpeed; @@ -384,14 +404,18 @@ canvas.addEventListener("mousemove", function (e) { colorArr = lerpColor(currentColor, targetColor, transitionProgress); count = 0; } - + pointers[0].down = true; pointers[0].color = colorArr; pointers[0].moved = pointers[0].down; - pointers[0].dx = (e.offsetX - pointers[0].x) * 10.0; - pointers[0].dy = (e.offsetY - pointers[0].y) * 10.0; - pointers[0].x = e.offsetX; - pointers[0].y = e.offsetY; + + // Aplicar multiplicador diferente según si estamos sobre texto o no + const multiplier = overText ? 8 : 10.0; // Reducido a 4x sobre texto (vs 10x) + + pointers[0].dx = (e.clientX - canvas.offsetLeft - pointers[0].x) * multiplier; + pointers[0].dy = (e.clientY - canvas.offsetTop - pointers[0].y) * multiplier; + pointers[0].x = e.clientX - canvas.offsetLeft; + pointers[0].y = e.clientY - canvas.offsetTop; }); canvas.addEventListener(