Animar componentes de React con GreenSock

 

 

 

  • Patrones de diseño para interfaces de IA, con Vitaly Friedman
  • ¡Registro!

  • Índice
    1. ¿Qué es GSAP? #
    2. ¿Por qué utilizar GSAP? #
      1. Puedes crear animaciones complejas #
      2. Actuación #
    3. Contras de GSAP #
    4. Conceptos básicos del GSAP #
      1. entre #
      2. métodos GSAP #
      3. Facilitando #
      4. Líneas de tiempo #
      5. Creación de una página de destino animada con React y GSAP #
      6. Definir métodos de animación. #
    5. Conclusión #
      1. Recursos #

    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.keyframeanimation

     

    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. EasingConsulte 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 keyframesen 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;

    1. methodse refiere al método GSAP con el que le gustaría realizar la interpolación.
    2. elementes el elemento que deseas animar. Si desea crear interpolaciones para varios elementos al mismo tiempo, puede pasar una matriz de elementos a element.
    3. durationes la duración de su interpolación. Es un número entero en segundos (¡sin el ssufijo!).
    4. varses 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 tométodo, la siguiente demostración de codepen muestra que un elemento con una clase de bola 250pxse moverá x-axisen cinco segundos cuando se monten los componentes. Si no se proporciona una duración, se utilizará un valor predeterminado de 500 milisegundos.

     

    Nota : xy y-axisrepresentan los ejes horizontal y vertical respectivamente, también en propiedades de transformación CSS como translateXy translateYse representan como xy ypara pixel-measuredtransformaciones y xPercentpara yPercenttransformaciones 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 squarese cambia el tamaño de un elemento con una clase de una escala de 4 pulgadas 3secondscuando 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étodo from()y to().

    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 balldesde una opacidad de 0 a una opacidad de 1a través del x-axisin 3 secondsy la squareclase se anima desde una opacidad de 0a 1in 3 secondsa través del x-axissolo cuando el componente se monta. Para ver cómo fromTofunciona 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 lefty top, debemos asegurarnos de que los elementos en cuestión tengan una propiedad de posición CSS de relative, absoluteo 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.

    1. in()— El movimiento comienza lentamente y luego acelera hacia el final de la animación.
    2. out()— La animación comienza rápido y luego se ralentiza al final de la animación.
    3. 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.outy 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 useEffectgancho, creamos una variable (tl)que contiene una instancia de una línea de tiempo, luego usamos la tlvariable 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. Trámites de notarias un USA para hispanos

    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 installpara 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 20degcuando 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 20degdesplazarse 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 componentcarpeta dentro del srcdirectorio y cree un animate.jsarchivo. 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 elempará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 , scalehace -1que el objeto easevuelva a entrar 2sec.

    Para ver si esto funciona, dirígete App.jse 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 textIntrométodo del Aminatecomponente. Para acceder al DOM utilizamos useRefHook. Creamos una variable introcuyo valor se establece en null. Luego, dentro del useEffectgancho, llamamos al textIntrométodo y a la introvariable. Dentro de nuestro componente de inicio, en la h5etiqueta, definimos el refaccesorio y pasamos la introvariable.

     

    A continuación, tenemos un menú, pero no se despliega cuando se hace clic en él. ¡Hagámoslo funcionar! Dentro del Header.jsComponente, 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 useEffectgancho, escuchamos los cambios de página usando useHistoryel gancho, si la página cambia establecemos los valores de estado clickedy en y respectivamente.menuNamefalseMenu

    Para manejar nuestro menú, verificamos si el valor de nuestro estado inicial es falso, si es verdadero, cambiamos el valor de initial, clickedy menuNamea null, truey Close. De lo contrario, verificamos si se hace clic en el botón; si es cierto, cambiaríamos el menuNamearchivo a Menu. A continuación, tenemos una disabledMenufunción que desactiva nuestro botón 1seccuando se hace clic en él.

    Por último, en nuestro button, le asignamos disableda disabledcuál es un valor booleano que deshabilitará el botón cuando su valor sea true. Y el onClickcontrolador del botón está vinculado a la toggleMenufunción. Todo lo que hicimos aquí fue alternar nuestro menutexto y pasar el estado a un Menucomponente, que crearíamos lo antes posible. Escribamos los métodos que harán que nuestro menú sea desplegable antes de crear el Menucomponente real. Dirígete Animate.jsy 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 staggerpropiedad y transforma el menú de right to topen 0.7sec; las mismas propiedades se aplican a la menuHidefunción. Para utilizar estas funciones, cree Menu.jsun archivo dentro componentsy 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 #

    1. Documentación GSAP , GreenSock
    2. “ La guía para principiantes de la plataforma de animación GreenSock ”, Nicholas Kramer, freeCodeCamp
    3. “ 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





    Tal vez te puede interesar:

    1. ¿Deberían abrirse los enlaces en ventanas nuevas?
    2. 24 excelentes tutoriales de AJAX
    3. 70 técnicas nuevas y útiles de AJAX y JavaScript
    4. Más de 45 excelentes recursos y repositorios de fragmentos de código

    Animar componentes de React con GreenSock

    Animar componentes de React con GreenSock

    Patrones de diseño para interfaces de IA, con Vitaly Friedman ¡Registro! Índice ¿Qué es GSAP? #

    programar

    es

    https://aprendeprogramando.es/static/images/programar-animar-componentes-de-react-con-greensock-1059-0.jpg

    2024-05-21

     

    Animar componentes de React con GreenSock
    Animar componentes de React con GreenSock

     

     

    Top 20