Animaciones y efectos de scroll en React JS con Framer Motion

María Simó
Secuoyas Experience
9 min readJul 8, 2020

Una guía práctica, personal y por partes para poner en movimiento tu sitio web por primera vez

Ilustrar.io — made by Gema Hoang @Secuoyas

El reto (o qué hace una chica como tú en un post como éste)

En Secuoyas, el pasado mes de marzo nos embarcamos en un proyecto de visualización de datos que vino motivado por la necesidad acuciante de tener información actualizada y depurada sobre la evolución de COVID-19 en España.

Con la finalidad de crear un espacio donde el análisis y consumo de datos fuese lo más sencillo y neutro posible, también dotamos a estos datos de un contexto y unas circunstancias, que nos permitieran unir todas las piezas y entender cómo y porqué estaban sucediendo las cosas.

Para ello, empleamos buena parte de nuestro tiempo en tener perfectamente alineados el backstage y frontstage de COVID·19-ES, y en mi caso, como front-end, centré todos mis esfuerzos en construir una sección de contexto donde el dinamismo y la vivacidad contrarrestaran la planitud de la página.

Una sección cuyos efectos de scroll te dan la profundidad necesaria para sumergirte en la historia de la pandemia, con una experiencia comunicativa mucho más ligera y cercana que otros medios.

En las próximas líneas te contaré minuciosamente cómo he llegado hasta aquí. Para qué sirven las animaciones en scroll y cómo puedes implementarlas dependiendo del stack tecnológico al que te enfrentes. Y en definitiva, cómo aprovechar estos recursos como complemento narrativo.

¡Allá vamos!

Un poco de benchmarking para alguien que nunca ha hecho animaciones en scroll

Css3 Animations

Crear una animación puede ser inicialmente tan fácil como poner en uso las propiedades de CSS3 Animations. Por ejemplo, puedes crear de manera muy sencilla un efecto de fade in de la siguiente manera:

Fácil e indoloro: https://codesandbox.io/s/css-animation-j63dc?file=/index.html

El método es bastante directo. Con CSS3 Animations puedes llegar a hacer animaciones muy interesantes, crear loops, aplicar delays, diferentes timmings, etc.

Es un recurso muy ágil pero limitado en el sentido de que esta aplicación se va a aplicar al elemento inmediatamente después de la carga de la página. Por tanto, en la mayoría de ocasiones, a no ser que el elemento esté posicionado above the fold, la animación va a ocurrir fuera de la vista del usuario.

Hoy en día, no existe un modo de involucrar el scroll en nuestras animaciones sólo por medio de CSS. Si queremos tener más control, necesitamos explorar los recursos que nos ofrece Javascript.

Librerías de Javascript

La idea general que se persigue es encontrar una herramienta que, como mínimo, nos ayude a calcular cuándo es el momento de iniciar una animación o, en casos más complejos, que nos ayude a sincronizar el propio movimiento del scroll con el desarrollo de la animación, en una relación directa entre la animación y el movimiento de scroll del usuario a lo largo de la página.

Nice and smooth

Para eso, tenemos a nuestra disposición algunas librerías específicas, que están dedicadas a una gestión integral de ese tipo de efectos, siendo la más popular de ellas ScrollMagic.

Cuando nunca has usado ScrollMagic con anterioridad (mi caso), es fácil caer en el error de pensar que con esta herramienta vas a poder desarrollar animaciones. No es así. ScrollMagic te va ayudar a controlar el scroll de tu página para mostrar las animaciones en el momento adecuado, pero no vas a poder desarrollar animaciones con esta herramienta.

Por elemental que pueda parecer, es importante diferenciar las dos partes que intervienen en este tipo de efectos: animación y scroll. En principio, cada una de estas partes la vamos a tener que gestionar con un recurso diferente.

Para la creación propiamente dicha de las animaciones, ScrollMagic recomienda directamente combinar su uso con Gsap (o si buscamos algo con menor impacto en performance, Velocity.js).

Gsap tiene una sintaxis relativamente sencilla para empezar, te permite crear y aplicar animaciones sencillas a elementos, de una manera que puede recordar a CSS3 animations. Si las animaciones van a ser muy complejas, como orquestaciones entre varios elementos, tal vez la escalabilidad y el control que permita Gsap sea mejor frente a la economía de medios de CSS3 animations.

Recientemente, la compañía creadora de Gsap, Greenstock, ha creado su propia herramienta de control de scroll, ScrollTrigger, y existen otras como Locomotive Scroll, Skrollr, etc.

En cualquier caso, la perspectiva es la de aprender dos librerías, ScrollMagic + Gsap, de carácter integral y extenso, para lograr el deseado efecto de animación en scroll.

Librerías en React

Por otra parte, la tecnología con la que el site de COVID·19-ES está construido es Gatsby, un framework de React. Eso implica que vamos a tener que trabajar con las versiones reactificadas de las librerías en las que deleguemos estas tareas.

React ScrollMagic nace para cubrir precisamente ese caso de uso. En esencia te ofrece un par de componentes, Controller y Scene, que actúan como wrappers y te permiten definir “una escena”. Lo que se consigue con esto es que elementos hijos de estos wrappers estén pineados durante el tiempo deseado, generando la oportunidad perfecta para animarlos.

Snippet extraído de la doc de React Scroll Magic.

También en su versión declarativa, ScrollMagic nos orienta a un uso combinado con Gsap. React Gsap, de manera similar a React ScrollMagic, ofrece una serie de componentes out of the box (Tween y Timeline, fundamentalmente) en los que la animación se define a través de props. Tal que así:

Snippet extraído de la doc de React ScrollMagic, que combina el uso de React ScrollMagic + React Gsap

Alternativas

Aunque son librerías muy consolidadas y con un uso muy extendido, sus versiones reactificadas no me parecían tan bien documentadas ni soportadas por la comunidad como las originales.

Una precaución adicional es que, aunque tienen ventaja de ofrecernos una funcionalidad out of the box (paso previo por los docs), en última instancia todo esto deriva en un montón de componentes extras, envolviendo nuestro contenido, lo cual resulta muy invasivo y añade una considerable cantidad de capas sobre nuestros componentes.

Parecía más adecuado encontrar otras opciones más lean, en lugar de comprometer el proyecto con algo, a primera vista, un poco desproporcionado.

Mi compañero Francis me había mencionado Framer Motion como herramienta para crear animaciones. Framer Motion es un desarrollo muy reciente de Framer (poco más de un año desde su primer release), pero que se puede usar de manera independiente. Después de ver este video en el que Chris Coyier conversa con Matt Perry, el creador de Framer Motion, estaba convencida de que nos ofrecía un montón de potencial.

Y yo no era la única intrigada con Framer Motion: https://twitter.com/dan_abramov/status/1184980257960550401

Me pareció que la curva de aprendizaje frente a Gsap era más suave, con la ventaja añadida de ser una librería concebida desde el principio para su uso con React, lo que resulta en una sintaxis más adaptada.

Lo mejor de todo, es que Framer Motion cuenta con un par de hooks propios, useViewportScroll y el recién sacado del horno useElementScroll, que te devuelven información sobre el recorrido del scroll. Con un poco de set up y la ayuda de estos hooks, es posible tener un “todo en uno”: una librería que permita animar nuestros elementos y además monitorear el avance del scroll.

Matt Perry usa mucho Twitter para comentar las novedades y posibilidades de Framer Motion: https://twitter.com/mattgperry/status/1261281246384132097

Además de Framer Motion, el segundo player a nivel de tecnología para este proyecto ha sido la API de Intersection Observer, que me ha servido para observar la posición de los elementos con respecto al viewport que quería animar en algunas de las animaciones. Lo he usado como alternativa al evento scroll, que es mucho más demandante a nivel de rendimiento.

Pero yo solo quería saber cómo están hechas las animaciones

Ok, al grano. En la página de contexto de COVID·19-ES hay distintos tipos de animaciones en las que se combina el uso de Framer Motion, Intersection Observer, la posición sticky y un par de React Hooks.

Animación de entrada

Una de las animaciones efectivas que podemos hacer es una simple animación de entrada. En esta animación, lo que hacemos es estar atentos de la posición del elemento y sólo cuando entre dentro del viewport, disparar una animación de fade in o similar.

Animación de entrada de elementos en viewport

Puedes usar como guía este sandbox que reproduce el efecto, con los elementos imprescindibles, y al que me voy a referir en esta última parte del artículo: https://codesandbox.io/s/secuoyas-covid-entrance-animation-6mksw

Lo que hacemos aquí, en líneas generales, es decir a Intersection Observer que permanezca atento a la posición de un outer div, que envuelve a los elementos que queremos animar. Para identificar el div que vamos a observar usamos el hook useRef. También tenemos que inicializar el estado del componente con el valor de false, por medio del hook useState.

Usando el hook useEffect e Intersection observer, creamos la lógica fundamental del componente: cuando este outer div interseccione con el viewport, actualizaremos el estado del componente, al que hemos llamado ‘inViewport’, a true.

Como nota aparte, si queremos hacer un uso más efectivo de estas líneas, podemos envolverlas en un custom hook, para usarlas una y otra vez como manera de detectar la entrada de elementos en el viewport. En la sección de recursos os apunto a un artículo que explica cómo hacerlo.

Después tenemos la definición de las animaciones en Framer motion. Aunque se pueden escribir las propiedades directamente sobre el componente, declararlas con esta notación de objeto y pasarlas al componente mediante la prop variants, nos da acceso a capacidades especiales, como orquestación y propagación a través del dom.

Además permite una sintaxis realmente limpia, pudiendo incluso agrupar todas nuestras animaciones en un archivo e importarlas en los componentes donde las necesitemos.

En este componente, creamos dos animaciones, una animación principal, llamada fadeInContainerWithStagger, que usamos para crear un efecto de stagger en los hijos del elemento al que está aplicada.

Otra animación para los hijos, fadeInUp, que tiene una transición de carácter ‘físico’ (spring).

Todo esto toma forma en el renderizado del componente, donde envolvemos los elementos que queremos animar en una condicional que usa el valor de inViewport, de manera que estén ocultos mientras su valor sea falso. Cuando el outer div entre en el viewport, ese valor pasará a ser true, y los componentes ahora se mostrarán usando las animaciones creadas con Framer Motion.

Eso es todo, por ahora 😃

Espero que compartir mi aprendizaje pueda servirte de algún modo, para descubrir alguna posibilidad nueva, incorporar otra opinión o reflejar tu propia experiencia.

En desarrollo, como sabes, hay muchas maneras de hacer las cosas, muchas herramientas y opciones a nuestro alcance que facilitan nuestro trabajo pero que complican la toma de decisiones. Así que me encantaría aprender de tu experiencia. ¿Te has enfrentado a este reto alguna vez? ¿Cómo lo has resuelto? ¿Qué forma de pensar te ha dado buen resultado? ¿De qué herramientas te has servido?

Atento, porque en las próximas semanas, seguiremos compartiendo otras técnicas de animación + scroll que hemos empleado en COVID·19-ES: Orquestación, Parallax y Scroll-driven Animations.

Siguiente artículo de la serie: Orquestación y animación de SVGs en React con Framer Motion (05/08/2020)

Recursos

- React Scroll Magic: https://www.npmjs.com/package/react-scrollmagic

- React Gsap: https://github.com/bitworking/react-gsap

- What’s the most powerful and developer-friendly React animation library? https://github.com/aholachek/react-animation-comparison

- A presentation of Framer Motion from Matt Perry in Chris Coyier youtube channel: https://www.youtube.com/watch?v=fY1pUeFqTsE

- Framer Motion official docs: https://www.youtube.com/watch?v=2V1WK-3HQNk&list=PL4cUxeGkcC9iHDnQfTHEVVceOEBsOf07i

- Playlist de Framer Motion The net ninja https://www.youtube.com/watch?v=2V1WK-3HQNk&list=PL4cUxeGkcC9iHDnQfTHEVVceOEBsOf07i

- Advance Animation Framer Motion https://shakuro.com/blog/framer-motion-tutorials-make-more-advanced-animations

- Framer Motion useElementScroll sandbox https://codesandbox.io/s/framer-motion-useelementscroll-2j2kg?file=/src/App.js:533-1589

- Twitter de Matt Perry, muy activo, con ejemplos de uso y novedades sobre Framer Motion: https://twitter.com/mattgperry

- An overview of scroll technologies: https://css-tricks.com/an-overview-of-scroll-technologies/

- An explanation of how the intersection observer watches: https://css-tricks.com/an-explanation-of-how-the-intersection-observer-watches/

- Custom Intersection Observer Hook: https://medium.com/@ger86/react-intersection-observer-hook-e57209493ce2

--

--

María Simó
Secuoyas Experience

Front end developer at Secuoyas. I studied Arts and then I realized art was anywhere else, so I became a designer, and after some years, a developer.