Cómo crear una animación SVG path draw al scroll en React
Para animar un path SVG que se dibuja solo al hacer scroll en React, usa useScroll de Framer Motion para obtener un valor scrollYProgress, mapéalo a un motion value pathLength con useTransform y aplícalo a un elemento motion.path. El trazo parece dibujarse a medida que la sección aparece en el viewport.
- Stack: React + Framer Motion 11 + CSS custom properties, ~46 líneas, cero dependencias adicionales.
- APIs principales: useScroll, useTransform, motion.path, el motion value pathLength.
- El path SVG se genera dinámicamente a partir del array de steps, así que añadir un paso extiende la línea automáticamente.
- Accesible: los títulos y descripciones de los pasos son texto DOM plano; el SVG es decorativo (no requiere ningún aria role).
- Responsive por defecto. En pantallas estrechas, el max-width y el padding-left del contenedor ajustan correctamente la disposición.
Process Path Draw es una timeline vertical de proceso donde una línea que conecta círculos numerados se dibuja sola a medida que haces scroll. El efecto de trazado sustituye una lista estática por un movimiento que refleja la idea de progreso: cada paso se revela en el momento en que llegas a él. Encaja de forma natural en flujos de onboarding, casos de estudio de agencia o secciones de producto tipo how-it-works.
Anatomía
Una sección a ancho completo contiene un header centrado (h2 + subtítulo) y una columna con ancho limitado (máx 680px). Dentro de esa columna, un SVG se posiciona en absoluto sobre el borde izquierdo, de 2rem de ancho, abarcando toda la altura de la columna. Renderiza dos paths superpuestos con atributos d idénticos: un path gris estático como raíl, y un motion.path de color accent cuyo pathLength se anima de 0 a 1. Las tarjetas de paso se colocan a la derecha del SVG, cada una con un círculo numerado posicionado en absoluto que se alinea con el path.
Cómo funciona
La clave está en el motion value pathLength de Framer Motion. Una ref sobre el contenedor exterior se pasa a useScroll con offset ['start 0.75', 'end 0.6'], lo que hace que scrollYProgress vaya de 0 a 1 a medida que el contenedor entra y atraviesa el viewport. useTransform mapea directamente ese rango 0-1 a un rango pathLength 0-1. Al aplicarlo a un elemento motion.path, Framer Motion anima la propiedad CSS stroke-dashoffset por debajo, que es el mecanismo nativo del navegador para dibujar paths SVG. Cada tarjeta de paso también aparece con un fundido mediante whileInView, escalonado por índice.
Cómo crearlo en React
Define la geometría del path a partir de tus pasos
Construye el atributo d del SVG mapeando tu array de steps. Cada paso se separa 180 unidades en vertical dentro de un viewBox de 100 unidades de ancho. Un cx=50 fijo mantiene la línea centrada en la columna SVG de 2rem.
const cx = 50; const pathD = steps .map((_, i) => `${i === 0 ? "M" : "L"} ${cx} ${i * 180 + 20}`) .join(" ");Vincula el progreso del scroll a pathLength
Asocia una ref al div contenedor y pásala a useScroll. El array offset controla en qué posiciones del scroll empieza y termina la animación. useTransform convierte el scrollYProgress bruto 0-1 en el motion value pathLength.
const containerRef = useRef<HTMLDivElement>(null); const { scrollYProgress } = useScroll({ target: containerRef, offset: ["start 0.75", "end 0.6"], }); const pathLength = useTransform(scrollYProgress, [0, 1], [0, 1]);Renderiza el SVG de dos capas
Coloca un SVG en absoluto junto a la columna de pasos. Dibuja primero el path gris estático como raíl visual, y luego el motion.path con el estilo pathLength. Ambos usan la misma cadena d. Establece preserveAspectRatio='none' para que la línea se estire hasta la altura real de la columna sin importar el número de pasos.
<motion.path d={pathD} stroke="var(--color-accent)" strokeWidth="3" strokeLinecap="round" style={{ pathLength }} />Alinea los marcadores de paso con la línea
Cada tarjeta de paso tiene position:relative. Dentro, un círculo posicionado en absoluto en left:-4.5rem coincide con el ancho de la columna SVG más el espacio. Un doble box-shadow (color de fondo y luego color accent) crea el efecto de 'nudo sobre la línea' sin ningún elemento DOM adicional.
Cuándo usarlo
Recurre a Process Path Draw cuando tengas de 3 a 5 pasos secuenciales y quieras dar peso visual a cada uno a medida que el usuario hace scroll. Funciona bien para explicaciones de onboarding, secciones de metodología en sitios de agencia y flujos de producto tipo how-it-works. Evítalo cuando los pasos sean realmente paralelos o cuando la página sea tan corta que la distancia de scroll no dispare la animación de forma significativa. En páginas con muchas otras animaciones al scroll, prueba el presupuesto de scroll combinado para evitar tirones.
Usado por
- Stripe, Usa paths verticales y líneas conectoras en sus secciones explicativas de producto para guiar la vista a través de un flujo de pago de varios pasos.
- Linear, Conectores animados entre pasos de workflow aparecen en sus páginas de features y changelog, reforzando la idea de progreso secuenciado.
- Lottiefiles, Las animaciones de timeline tipo path-draw son un formato destacado en la plataforma, demostrando la técnica en páginas de marketing.
FAQ
¿Cómo controlo la velocidad de la animación de dibujo?
Ajusta el array offset en useScroll. Un rango más ajustado como ['start 0.6', 'end 0.8'] hace que el dibujo ocurra más rápido en una distancia de scroll más corta. Ampliarlo a ['start 0.9', 'end 0.2'] lo ralentiza a lo largo de un rango de scroll más largo.
¿Puedo usar un path curvo en lugar de líneas rectas?
Sí. Sustituye los comandos M/L en pathD por curvas de Bézier usando comandos C o Q. La animación pathLength funciona con cualquier path SVG válido, así que la técnica es agnóstica a la geometría.
¿Por qué el SVG usa preserveAspectRatio='none'?
La altura del viewBox se calcula a partir del número de pasos (steps.length * 180), pero la altura renderizada del SVG es el 100% del contenedor. Sin preserveAspectRatio='none', el navegador aplicaría un letterbox o recortaría el path. El valor 'none' estira la geometría del path para rellenar el elemento exactamente.
¿La animación se vuelve a reproducir cuando el usuario sube de nuevo?
El pathLength es un motion value en vivo ligado a la posición del scroll, así que se invierte de forma natural al subir de nuevo. Las tarjetas de paso usan whileInView con once:true, por lo que permanecen visibles tras su primera aparición.