Animar componentes de React con GreenSock

GreenSock Animation Platform (GSAP) es un conjunto de funciones de JavaScript que le permiten intercalar un valor/atributo/propiedad CSS a lo largo del tiempo e insertar estas interpolaciones en una línea de tiempo para animaciones más complejas. En este artículo, Blessing explica cómo GSAP funciona bien con la biblioteca React al integrar sus funciones en un componente de React para crear una página de inicio de ejemplo con una variedad de animaciones.
Durante los primeros días de la World Wide Web, las cosas eran bastante estáticas y aburridas. Las páginas web se basaban principalmente en diseños gráficos y maquetaciones del mundo impreso hasta que se introdujeron las animaciones. La animación puede atraer y mantener la atención de las personas por más tiempo que una página web estática y comunica una idea o concepto de manera más clara y efectiva.
Sin embargo, cuando no se hacen correctamente, las animaciones pueden obstaculizar las interacciones del usuario con su producto y afectar negativamente la tracción. GreenSock Animation Platform AKA (GSAP) es una poderosa biblioteca de JavaScript que permite a los desarrolladores, animadores y diseñadores de aplicaciones para el usuario crear animaciones de alto rendimiento basadas en líneas de tiempo. Permite a los amantes de la animación tomar un control preciso de sus secuencias de animación en lugar de las propiedades y restricciones que ofrece CSS.keyframe
animation
En este artículo, le presentaré algunas características de GSAP como scrollTriggers
, etc., al final crearemos una interfaz de usuario intuitiva animando una aplicación React con estas características Timelines
. Easing
Consulte el proyecto terminado en codesandbox .
Este artículo te será útil si:
- Ha estado creando animaciones en aplicaciones web con HTML, CSS y JavaScript.
- Ya estás creando páginas web animadas en aplicaciones React con paquetes como animate.css, React-motion , Framer-motion y React-Spring , y además quieres probar alternativas.
- Eres un entusiasta de React y te gustaría crear animaciones complejas en aplicaciones web basadas en React.
Veremos cómo crear una variedad de animaciones a partir de un proyecto web existente. ¡Hagámoslo!
Nota : este artículo supone que se siente cómodo con HTML, CSS, JavaScript y React.js.
¿Qué es GSAP? #
La plataforma de animación GreenSock, también conocida como GSAP, es una animación de nivel profesional y de rendimiento ultraalto para la web moderna que permite a los desarrolladores animar sus aplicaciones de forma modular, declarativa y reutilizable. Es independiente del marco y se puede utilizar en cualquier proyecto basado en JavaScript, tiene un tamaño de paquete mínimo y no inflará su aplicación.
GSAP puede realizar animaciones de lienzo, utilizadas para crear experiencias WebGL y crear animaciones SVG dinámicas y como excelente soporte para navegador.
¿Por qué utilizar GSAP? #
Tal vez aún no esté listo para traicionar otros marcos, o no esté convencido de aceptar las ventajas que vienen con GSAP. Permítame darle algunas razones por las que quizás desee considerar GSAP.
Puedes crear animaciones complejas #
La biblioteca GSAP JavaScript hace posible que los desarrolladores creen animaciones basadas en la física desde simples hasta muy complejas, como en el caso de estos sitios , permite a los desarrolladores y diseñadores secuenciar el movimiento y controlar la animación dinámicamente. Tiene muchos complementos como DrawSVGPlugin , MorphSVGPlugin y más , lo que hace que la creación de animaciones basadas en SVG y animaciones 2D/3D sea una realidad. Además de integrar GSAP en elementos DOM, puede usarlos dentro de animaciones basadas en contexto WebGL / Canvas /Three.js.
Además, la capacidad de facilitación de GSAP es bastante sofisticada, por lo que permite crear efectos avanzados con múltiples beziers en comparación con la animación CSS normal .
Actuación #
GSAP tiene un alto rendimiento impresionante en diferentes navegadores.
Según el equipo de GSAP, en su sitio web , “GSAP es 20 veces más rápido que jQuery, además GSAP es la herramienta de animación con script con todas las funciones más rápida del planeta. En muchos casos , es incluso más rápido que las animaciones y transiciones CSS3 ”. Confirme usted mismo la comparación de velocidades .
Además, las animaciones GSAP funcionan sin esfuerzo tanto en computadoras de escritorio, tabletas y teléfonos inteligentes. No es necesario agregar una larga lista de prefijos, GSAP se encarga de todo esto.
Puede consultar más beneficios en GSAP o ver lo que Sarah Drasner dice al respecto aquí .
Contras de GSAP #
¿Estás diciendo que siempre debería usar GSAP para cada proyecto? ¡Por supuesto que no! Siento que solo hay una razón por la que quizás no quieras usar GSAP. ¡Vamos a averiguar!
- GSAP es únicamente una biblioteca de animación basada en JavaScript, por lo que requiere cierto conocimiento de manipulación de JavaScript y DOM para utilizar eficazmente sus métodos y API. Esta desventaja de la curva de aprendizaje deja aún más espacio para complicaciones para un principiante que comienza con JavaScript.
- GSAP no admite animaciones basadas en CSS, por lo tanto, si está buscando una biblioteca para estas, también puede utilizarla
keyframes
en animaciones CSS.
Si tienes algún otro motivo, no dudes en compartirlo en la sección de comentarios.
Muy bien, ahora que tus dudas están despejadas, pasemos al meollo de la cuestión en GSAP.
Conceptos básicos del GSAP #
Antes de crear nuestra animación usando React, familiaricémonos con algunos métodos y componentes básicos de GSAP.
Si ya conoce los fundamentos de GSAP, puede omitir esta sección y pasar directamente a la sección del proyecto, donde distorsionaremos la página de destino mientras nos desplazamos.
entre #
Una interpolación es un movimiento único en una animación. En GSAP, una interpolación tiene la siguiente sintaxis:
TweenMax.method(element, duration, vars)
Echemos un vistazo a lo que representa esta sintaxis;
method
se refiere al método GSAP con el que le gustaría realizar la interpolación.element
es el elemento que deseas animar. Si desea crear interpolaciones para varios elementos al mismo tiempo, puede pasar una matriz de elementos aelement
.duration
es la duración de su interpolación. Es un número entero en segundos (¡sin els
sufijo!).vars
es un objeto de las propiedades que desea animar. Más sobre esto más adelante.
métodos GSAP #
GSAP proporciona numerosos métodos para crear animaciones. En este artículo, mencionaremos solo algunos como gsap.to
, gsap.from
, gsap.fromTo
. Puedes consultar otros métodos interesantes en su documentación . Los métodos discutidos en esta sección se utilizarán en la construcción de nuestro proyecto más adelante en este tutorial.
gsap.to()
los valores a los que se debe animar un objeto, es decir, los valores de propiedad finales de un objeto animado, como se muestra a continuación:
gsap.to('.ball', {x:250, duration: 5})
Para demostrar el to
método, la siguiente demostración de codepen muestra que un elemento con una clase de bola 250px
se moverá x-axis
en cinco segundos cuando se monten los componentes. Si no se proporciona una duración, se utilizará un valor predeterminado de 500 milisegundos.
Nota : x
y y-axis
representan los ejes horizontal y vertical respectivamente, también en propiedades de transformación CSS como translateX
y translateY
se representan como x
y y
para pixel-measured
transformaciones y xPercent
para yPercent
transformaciones basadas en porcentajes.
Para ver el fragmento completo del código, consulte el área de juegos de codepen.
gsap.from()
— Define los valores a partir de los cuales se debe animar un objeto, es decir, los valores iniciales de una animación:
gsap.from('.square', {duration:3, scale: 4})
La demostración de codepen muestra cómo square
se cambia el tamaño de un elemento con una clase de una escala de 4 pulgadas 3seconds
cuando se montan los componentes. Busque el fragmento de código completo en este codepen.
gsap.fromTo()
: le permite definir los valores inicial y final de una animación. Es una combinación del métodofrom()
yto()
.
Así es como se ve;
gsap.fromTo('.ball',{opacity:0 }, {opacity: 1 , x: 200 , duration: 3 });gsap.fromTo('.square', {opacity:0, x:200}, { opacity:1, x: 1 , duration: 3 });
Este código animaría el elemento con una clase ball
desde una opacidad de 0 a una opacidad de 1
a través del x-axis
in 3 seconds
y la square
clase se anima desde una opacidad de 0
a 1
in 3 seconds
a través del x-axis
solo cuando el componente se monta. Para ver cómo fromTo
funciona el método y el fragmento de código completo, consulte la demostración en CodePen a continuación.
Nota : Siempre que estemos animando propiedades posicionales, como left
y top
, debemos asegurarnos de que los elementos en cuestión tengan una propiedad de posición CSS de relative
, absolute
o fixed
.
Facilitando #
La documentación oficial de GSAP definió la flexibilización como la forma principal de cambiar el tiempo de sus Tweens. Determina cómo un objeto cambia de posición en diferentes puntos. Facilidad controla la tasa de cambio de animación en GSAP y se utiliza para establecer el estilo de la animación de un objeto.
GSAP proporciona diferentes tipos de facilidades y opciones para brindarle más control sobre cómo debe comportarse su animación. También proporciona un Visualizador de facilidad para ayudarlo a elegir su configuración de facilidad preferida.
Hay tres tipos de facilidades y varían en sus operaciones.
in()
— El movimiento comienza lentamente y luego acelera hacia el final de la animación.out()
— La animación comienza rápido y luego se ralentiza al final de la animación.inOut()
— La animación comienza lenta, acelera el ritmo a la mitad y termina lentamente.
En este ejemplo de aceleración, encadenamos las interpolaciones que mostraban los tres tipos de aceleración bounce.in
, bounce.out
y bounce.inOut
, y establecimos un retraso de la cantidad de segundos que tarda la animación en completarse antes de comenzar la siguiente solo cuando el componente está montado. Este patrón es repetitivo; en la siguiente sección veremos cómo podríamos usar una línea de tiempo para hacerlo mejor.
- Aproveche la sólida recuperación de datos y el tamaño de paquete optimizado con KendoReact Server Data Grid Probar ahora
Líneas de tiempo #
Una línea de tiempo actúa como contenedor para múltiples interpolaciones. Anima las interpolaciones en orden secuencial y no depende de la duración de la interpolación anterior. Timeline simplifica el control de los preadolescentes en su conjunto y gestiona con precisión su sincronización.
Las líneas de tiempo se pueden escribir creando una instancia de una línea de tiempo como esta:
gsap.timeline();
También puedes encadenar varias interpolaciones a una línea de tiempo de dos maneras diferentes, en el siguiente código:
##Method 1const tl = gsap.timeline(); // create an instance and assign it a variabletl.add(); // add tween to timeline tl.to('element', {});tl.from('element', {});##Method 2gsap.timeline() .add() // add tween to timeline .to('element', {}) .from('element', {})
Recreemos el ejemplo anterior con una línea de tiempo:
const { useRef, useEffect } = React;const Balls = () = { useEffect(() = { const tl = gsap.timeline(); tl.to('#ball1', {x:1000, ease:"bounce.in", duration: 3}) tl.to('#ball2', {x:1000, ease:"bounce.out", duration: 3, delay:3 }) tl.to('#ball3', {x:1000, ease:"bounce.inOut", duration: 3, delay:6 }) }, []);}ReactDOM.render(, document.getElementById('app'));
Dentro de un useEffect
gancho, creamos una variable (tl)
que contiene una instancia de una línea de tiempo, luego usamos la tl
variable para animar nuestra interpolación en secuencia sin depender de la interpolación anterior para animar, pasando las mismas propiedades que en el ejemplo anterior. Para obtener el fragmento de código completo de esta demostración, consulte el área de juegos de codepen a continuación.
Ahora que hemos tenido una idea de algunos de los componentes básicos de GSAP, veamos cómo podríamos crear una animación completa en una aplicación React típica en la siguiente sección. ¡Comencemos el vuelo!
Creación de una página de destino animada con React y GSAP #
Empecemos a animar una aplicación React. Asegúrese de clonar el repositorio antes de comenzar y ejecutarlo npm install
para instalar las dependencias.
¿Qué estamos construyendo? #
Actualmente, nuestra página de inicio contiene algunos textos con un fondo blanco, un menú que no se despliega y realmente no tiene animación. Lo siguiente es lo que agregaremos a la página de inicio;
- Anime el texto y el logotipo en la página de inicio, para que desaparezca cuando se monte el componente.
- Anime el menú para que se despliegue cuando se haga clic en él.
- Haga que las imágenes en la página de la galería se inclinen
20deg
cuando la página se desplaza.
Vea la demostración en codesandbox .
Dividiremos el proceso de nuestra página de destino en componentes, para que sea fácil de entender. Aquí está el proceso;
- Definir los métodos de animación.
- Animar texto y logotipo,
- Alternar menú,
- Haga que las imágenes se inclinen al
20deg
desplazarse por la página.
componentes
Animate.js
- Definió todos los métodos de animación,Image.js
- importar imágenes de galera,Menu.js
— Contiene la función de alternancia de menú,Header.js
— Contiene enlaces de navegación.
Definir métodos de animación. #
Cree una component
carpeta dentro del src
directorio y cree un animate.js
archivo. Copie y pegue el siguiente código en él.
import gsap from "gsap"import { ScrollTrigger } from "gsap/ScrollTrigger";//Animate text export const textIntro = elem = { gsap.from(elem, { xPercent: -20, opacity: 0, stagger: 0.2, duration: 2, scale: -1, ease: "back", });};
Aquí importamos gsap
. Escribimos una función de flecha exportada que anima el texto en la página de destino. Recuerde que el gsap.from()
método define los valores a partir de los cuales se debe animar un objeto. La función tiene un elem
parámetro que representa la clase que necesita ser animada. Toma algunas propiedades y asigna valores como xPercent: -20
(transforma el objeto en -20%), no le da opacidad al objeto , scale
hace -1
que el objeto ease
vuelva a entrar 2sec
.
Para ver si esto funciona, dirígete App.js
e incluye el siguiente código.
...//import textIntroimport {textIntro} from "./components/Animate"...//using useRef hook to access the textIntro DOM let intro = useRef(null) useEffect(() = { textIntro(intro) }, [])function Home() { return ( div className='container' div className='wrapper' h5 className="intro" ref={(el) = (intro = el)}/h5 The bSHOPPER/b, is a worldclass, innovative, global online ecommerce platform, that meets your everyday daily needs. /h5 /div /div );}
Aquí, importamos el textIntro
método del Aminate
componente. Para acceder al DOM utilizamos useRef
Hook. Creamos una variable intro
cuyo valor se establece en null
. Luego, dentro del useEffect
gancho, llamamos al textIntro
método y a la intro
variable. Dentro de nuestro componente de inicio, en la h5
etiqueta, definimos el ref
accesorio y pasamos la intro
variable.
A continuación, tenemos un menú, pero no se despliega cuando se hace clic en él. ¡Hagámoslo funcionar! Dentro del Header.js
Componente, agregue el siguiente código.
import React, { useState, useEffect, useRef } from "react";import { withRouter, Link, useHistory } from "react-router-dom";import Menu from "./Menu";const Header = () = { const history = useHistory() let logo = useRef(null); //State of our Menu const [state, setState] = useState({ initial: false, clicked: null, menuName: "Menu", }); // State of our button const [disabled, setDisabled] = useState(false); //When the component mounts useEffect(() = { textIntro(logo); //Listening for page changes. history.listen(() = { setState({ clicked: false, menuName: "Menu" }); }); }, [history]); //toggle menu const toggleMenu = () = { disableMenu(); if (state.initial === false) { setState({ initial: null, clicked: true, menuName: "Close", }); } else if (state.clicked === true) { setState({ clicked: !state.clicked, menuName: "Menu", }); } else if (state.clicked === false) { setState({ clicked: !state.clicked, menuName: "Close", }); } }; // check if out button is disabled const disableMenu = () = { setDisabled(!disabled); setTimeout(() = { setDisabled(false); }, 1200); }; return ( header div className="container" div className="wrapper" div className="inner-header" div className="logo" ref={(el) = (logo = el)} Link to="/"SHOPPER./Link /div div className="menu" button disabled={disabled} onClick={toggleMenu} {state.menuName} /button /div /div /div /div Menu state={state} / /header );};export default withRouter(Header);
En este componente, definimos el estado de nuestro menú y botón, dentro del useEffect
gancho, escuchamos los cambios de página usando useHistory
el gancho, si la página cambia establecemos los valores de estado clicked
y en y respectivamente.menuName
false
Menu
Para manejar nuestro menú, verificamos si el valor de nuestro estado inicial es falso, si es verdadero, cambiamos el valor de initial
, clicked
y menuName
a null
, true
y Close
. De lo contrario, verificamos si se hace clic en el botón; si es cierto, cambiaríamos el menuName
archivo a Menu
. A continuación, tenemos una disabledMenu
función que desactiva nuestro botón 1sec
cuando se hace clic en él.
Por último, en nuestro button
, le asignamos disabled
a disabled
cuál es un valor booleano que deshabilitará el botón cuando su valor sea true
. Y el onClick
controlador del botón está vinculado a la toggleMenu
función. Todo lo que hicimos aquí fue alternar nuestro menu
texto y pasar el estado a un Menu
componente, que crearíamos lo antes posible. Escribamos los métodos que harán que nuestro menú sea desplegable antes de crear el Menu
componente real. Dirígete Animate.js
y pega este código en él.
....//Open menuexport const menuShow = (elem1, elem2) = { gsap.from([elem1, elem2], { duration: 0.7, height: 0, transformOrigin: "right top", skewY: 2, ease: "power4.inOut", stagger: { amount: 0.2, }, });};//Close menuexport const menuHide = (elem1, elem2) = { gsap.to([elem1, elem2], { duration: 0.8, height: 0, ease: "power4.inOut", stagger: { amount: 0.07, }, });};
Aquí, tenemos una función llamada menuShow
, que inclina el menú horizontalmente 2degrees
, facilita el menú, compensa la animación usando la stagger
propiedad y transforma el menú de right to top
en 0.7sec
; las mismas propiedades se aplican a la menuHide
función. Para utilizar estas funciones, cree Menu.js
un archivo dentro components
y pegue este código en él.
import React, {useEffect, useRef} from 'react'import { gsap } from "gsap"import { Link } from "react-router-dom"import { menuShow, menuHide, textIntro,} from './Animate'const Menu = ({ state }) = { //create refs for our DOM elements let menuWrapper = useRef(null) let show1 = useRef(null) let show2 = useRef(null) let info = useRef(null) useEffect(() = { // If the menu is open and we click the menu button to close it. if (state.clicked === false) { // If menu is closed and we want to open it. menuHide(show2, show1); // Set menu to display none gsap.to(menuWrapper, { duration: 1, css: { display: "none" } }); } else if ( state.clicked === true || (state.clicked === true state.initial === null) ) { // Set menu to display block gsap.to(menuWrapper, { duration: 0, css: { display: "block" } }); //Allow menu to have height of 100% gsap.to([show1, show2], { duration: 0, opacity: 1, height: "100%" }); menuShow(show1, show2); textIntro(info); } }, [state]) return ( div ref={(el) = (menuWrapper = el)} className="hamburger-menu" div ref={(el) = (show1 = el)} className="menu-secondary-background-color" /div div ref={(el) = (show2 = el)} className="menu-layer" div className="container" div className="wrapper" div className="menu-links" nav ul li Link ref={(el) = (line1 = el)} to="/about-us" About /Link /li li Link ref={(el) = (line2 = el)} to="/gallery" Gallery /Link /li li Link ref={(el) = (line3 = el)} to="/contact-us" Contact us /Link /li /ul /nav div ref={(el) = (info = el)} className="info" h3Our Vision/h3 p Lorem ipsum dolor sit amet consectetur adipisicing elit.... /p /div /div /div /div /div /div );}export default Menu
What we did in the Menu
component was to import the animated functions, which are menuShow
, menuHide
, and textIntro
. Next, we assigned variables for each created refs
for our DOM
elements using the useRef
hook and passed null
as their values. Inside the useEffect
hook, we check for the state of the menu
, if clicked
is false
, we call the menuHide
function, otherwise, if the clicked
state is true we call the menuShow
function. Lastly, we ensured that the DOM
elements concerned are passed their specific refs
which are menuWrapper
, show1
, show2
. With that, we’ve got our menu animated.
Let’s see how it looks.
The last animation we would implement is make our images in our gallery skew
when it scrolls. Let’s see the state of our gallery now.
To implement the skew animation on our gallery, let’s head over to Animate.js
and add a few codes to it.
....//Skew gallery Imagesexport const skewGallery = elem1 = { //register ScrollTrigger gsap.registerPlugin(ScrollTrigger); // make the right edge "stick" to the scroll bar. force3D: true improves performance gsap.set(elem1, { transformOrigin: "right center", force3D: true }); let clamp = gsap.utils.clamp(-20, 20) // don't let the skew go beyond 20 degrees. ScrollTrigger.create({ trigger: elem1, onUpdate: (self) = { const velocity = clamp(Math.round(self.getVelocity() / 300)); gsap.to(elem1, { skew: 0, skewY: velocity, ease: "power3", duration: 0.8, }); }, });}
We created a function called skewGallery
, passed elem1
as a param, and registered ScrollTrigger
.
ScrollTrigger is a plugin in GSAP that enables us to trigger scroll-based animations, like in this case of skewing the images while the page scrolls.
To make the right edge stick to the scroll bar we passed right center
value to the transformOrigin
property, we also set the force3D
property to true in other to improve the performance.
We declared a clamp
variable that calculates our skew and ensures it doesn’t exceed 20degs
. Inside the ScrollTrigger
object, we assigned the trigger
property to the elem1
param, which would be the element that needs to be triggered when we call this function. We have an onUpdate
callback function, inside it is a velocity
variable that calculates the current velocity and divides it by 300
.
Lastly, we animate the element from their current values by setting other values. We set skew
to initially be at 0
and skewY
to be the velocity
variable at 0.8
.
Next, we’ve got to call this function in our App.js
file.
....import { skewGallery } from "./components/Animate"function Gallery() { let skewImage = useRef(null); useEffect(() = { skewGallery(skewImage) }, []); return ( div ref={(el) = (skewImage = el)} Image/ /div )}....
Here, we imported skewGalley
from ./components/Animate
, created a skewImage
ref that targets the image element. Inside the useEffect
hook, we called the skewGallery
function and passed the skewImage
ref as a param. Lastly, we passed the skewImage
to the ref
to attribute.
You’d agree with me it was such a pretty cool journey thus far. Here’s the preview on CodeSanbox
The supporting repo for this article is available on Github.
Conclusión #
Hemos explorado la potencia de GSAP en un proyecto de React, solo arañamos la superficie en este artículo, no hay límite para lo que puedes hacer con GSAP en lo que respecta a la animación. El sitio web oficial de GSAP ofrece consejos adicionales para ayudarle a obtener una comprensión profunda de los métodos y complementos. Hay muchas demostraciones que te dejarán boquiabierto con lo que la gente ha hecho con GSAP. Me encantaría escuchar tu experiencia con GSAP en la sección de comentarios.
Recursos #
- Documentación GSAP , GreenSock
- “ La guía para principiantes de la plataforma de animación GreenSock ”, Nicholas Kramer, freeCodeCamp
- “ Introducción a las animaciones con la API de animación Greensock (GSAP) ”, Zell Liew
(ks, ra, yk, il)Explora más en
- Aplicaciones
- Nativo
- Reaccionar
- Animación
- javascript
Deja un comentario