React Animation - GSAP

Vitthal KorvanVitthal Korvan
7 min read

GSAP in React

Using GSAP (GreenSock Animation Platform) in React

GSAP (GreenSock Animation Platform) is a powerful animation library for JavaScript that works well with React. It allows you to create high-performance animations with ease.

Here's a step-by-step guide to using GSAP in React, along with some examples:

Step-by-Step Guide

1. Install GSAP

You can install GSAP in your React project using npm or yarn.

npm install gsap
# or
yarn add gsap

2. Import GSAP in Your Component

After installing GSAP, you can import the necessary modules in your React components.

import { gsap } from 'gsap';

3. Create References for Elements to Animate

In React, GSAP animations are typically applied to DOM elements. You can use the useRef hook to create a reference to the DOM element you want to animate.

import React, { useRef, useEffect } from 'react';
import { gsap } from 'gsap';

const MyComponent = () => {
  const boxRef = useRef(null);

  useEffect(() => {
    gsap.to(boxRef.current, { rotation: 360, duration: 2 });
  }, []);

  return (
    <div>
      <div ref={boxRef} style={styles.box}></div>
    </div>
  );
};

const styles = {
  box: {
    width: '100px',
    height: '100px',
    backgroundColor: 'red',
  },
};

export default MyComponent;

In this example:

  • boxRef is used to reference the div element.

  • GSAP rotates the element 360 degrees over 2 seconds.

GSAP Animation Example : GSAP Example 1

4. Controlling Animations with State

You can also trigger animations based on component state. For example, animating an element when a button is clicked.

import React, { useRef, useState } from 'react';
import { gsap } from 'gsap';

const MyComponent = () => {
  const boxRef = useRef(null);
  const [isAnimating, setAnimating] = useState(false);

  const animateBox = () => {
    gsap.to(boxRef.current, { x: isAnimating ? 0 : 200, duration: 1 });
    setAnimating(!isAnimating);
  };

  return (
    <div>
      <div ref={boxRef} style={styles.box}></div>
      <button onClick={animateBox}>Animate</button>
    </div>
  );
};

const styles = {
  box: {
    width: '100px',
    height: '100px',
    backgroundColor: 'red',
  },
};

export default MyComponent;

5. Using Timelines in GSAP

GSAP provides a Timeline feature to sequence animations. This allows multiple animations to run in succession.

import React, { useRef, useEffect } from 'react';
import { gsap, TimelineLite } from 'gsap';

const MyComponent = () => {
  const box1Ref = useRef(null);
  const box2Ref = useRef(null);
  const box3Ref = useRef(null);

  useEffect(() => {
    const tl = gsap.timeline();
    tl.to(box1Ref.current, { x: 100, duration: 1 })
      .to(box2Ref.current, { x: 100, duration: 1 })
      .to(box3Ref.current, { x: 100, duration: 1 });
  }, []);

  return (
    <div>
      <div ref={box1Ref} style={styles.box}></div>
      <div ref={box2Ref} style={styles.box}></div>
      <div ref={box3Ref} style={styles.box}></div>
    </div>
  );
};

const styles = {
  box: {
    width: '100px',
    height: '100px',
    backgroundColor: 'blue',
    marginBottom: '10px',
  },
};

export default MyComponent;

In this example:

  • The three boxes will move to the right sequentially, one after the other.

GSAP X TimeLine : Timeline GSAP code

6. Reversing Animations

You can reverse GSAP animations easily by calling .reverse() on the timeline or animation.

import React, { useRef, useEffect, useState } from 'react';
import { gsap } from 'gsap';

const MyComponent = () => {
  const boxRef = useRef(null);
  const [isReversed, setIsReversed] = useState(false);

  useEffect(() => {
    gsap.to(boxRef.current, { rotation: 360, duration: 2 });
  }, []);

  const toggleReverse = () => {
    const animation = gsap.to(boxRef.current, { rotation: 360, duration: 2 });
    if (isReversed) {
      animation.reverse();
    }
    setIsReversed(!isReversed);
  };

  return (
    <div>
      <div ref={boxRef} style={styles.box}></div>
      <button onClick={toggleReverse}>
        {isReversed ? 'Play' : 'Reverse'}
      </button>
    </div>
  );
};

const styles = {
  box: {
    width: '100px',
    height: '100px',
    backgroundColor: 'green',
  },
};

export default MyComponent;

Example Scenarios

Example 1: Fading in Elements

useEffect(() => {
  gsap.fromTo(boxRef.current, { opacity: 0 }, { opacity: 1, duration: 2 });
}, []);

This will animate the opacity of the boxRef element from 0 (invisible) to 1 (fully visible) over 2 seconds.

Example 2: Animating Multiple Elements

useEffect(() => {
  gsap.to(".box", { x: 100, stagger: 0.2, duration: 1 });
}, []);

Using the stagger property, GSAP will animate elements with the class box one after another with a 0.2-second delay between each.

Example 3: Using ScrollTrigger (GSAP Plugin)

npm install gsap@npm:@gsap/shockingly
import { gsap } from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";

gsap.registerPlugin(ScrollTrigger);

useEffect(() => {
  gsap.to(boxRef.current, {
    x: 500,
    scrollTrigger: {
      trigger: boxRef.current,
      start: "top center",
      end: "bottom top",
      scrub: true,
    },
  });
}, []);

In this example, the ScrollTrigger plugin animates an element based on scroll position.

Key Concepts to Remember:

  1. References: Use useRef to reference DOM elements.

  2. useEffect: Use GSAP animations within the useEffect hook to ensure the DOM elements have been rendered.

  3. Timelines: Use gsap.timeline() to sequence multiple animations.

  4. Reversing: Use .reverse() to reverse animations easily.

Key GSAP Parameters and their Usage

  1. target (Required)

    • The element(s) to animate. In React, this is usually referenced using useRef.

    • Can be a single element, an array of elements, or a string selector (e.g., ".my-class").

    • Example:

        gsap.to(boxRef.current, { duration: 1, x: 100 });
      
  2. duration

    • Specifies how long the animation should take (in seconds).

    • Default: 0.5 seconds.

    • Example:

        gsap.to(boxRef.current, { duration: 2, x: 200 });
      
  3. x, y, z

    • Moves the element along the respective axis (in pixels).

    • Example:

        gsap.to(boxRef.current, { duration: 1, x: 300, y: 200 });
      
  4. opacity

    • Fades the element in or out by adjusting the opacity (between 0 and 1).

    • Example:

        gsap.to(boxRef.current, { duration: 1, opacity: 0.5 });
      
  5. scale, scaleX, scaleY

    • Scales the element (1 is default size).

    • Example:

        gsap.to(boxRef.current, { duration: 1, scale: 1.5 });
      
  6. rotation

    • Rotates the element in degrees (clockwise is positive, counter-clockwise is negative).

    • Example:

        gsap.to(boxRef.current, { duration: 1, rotation: 360 });
      
  7. ease

    • Controls the easing function, defining how the animation accelerates or decelerates.

    • Common values: "power1.in", "power2.out", "elastic", "bounce", "linear".

    • Example:

        gsap.to(boxRef.current, { duration: 1, x: 100, ease: "power3.out" });
      
  8. delay

    • Adds a delay (in seconds) before starting the animation.

    • Example:

        gsap.to(boxRef.current, { duration: 1, x: 200, delay: 0.5 });
      
  9. repeat

    • Defines how many times the animation should repeat.

    • Set -1 for infinite repetition.

    • Example:

        gsap.to(boxRef.current, { duration: 1, x: 100, repeat: 3 });
      
  10. yoyo

    • When set to true, the animation will reverse after reaching the end (useful with repeat).

    • Example:

        gsap.to(boxRef.current, 
        { duration: 1, x: 100, repeat: 2, yoyo: true });
      
  11. stagger

    • Animates multiple elements with a staggered delay.

    • Example:

        gsap.to(".box", { duration: 1, x: 100, stagger: 0.2 });
      
  12. onComplete, onStart, onUpdate

    • These are callbacks that fire at specific points in the animation lifecycle.

    • onComplete: Fires when the animation finishes.

    • onStart: Fires when the animation starts.

    • onUpdate: Fires every time the values are updated.

    • Example:

        gsap.to(boxRef.current, { 
          duration: 1, 
          x: 100, 
          onComplete: () => console.log("Animation Complete!") 
        });
      
  13. from vs to

    • GSAP has both gsap.from() and gsap.to() methods.

    • gsap.from() starts the animation from a set of initial values, animating to the element's current state.

    • gsap.to() animates from the current state to the provided values.

    • Example (from):

        gsap.from(boxRef.current, { duration: 1, opacity: 0 });
      
  14. paused

    • If set to true, the animation will start in a paused state and can be triggered later.

    • Example:

        const animation = gsap.to(boxRef.current, 
        { duration: 1, x: 100, paused: true });
        animation.play(); // Trigger it later
      

Example Usage in React

import React, { useRef, useEffect } from 'react';
import { gsap } from 'gsap';

const GsapComponent = () => {
  const boxRef = useRef(null);

  useEffect(() => {
    gsap.to(boxRef.current, {
      duration: 1,     // 1 second animation duration
      x: 100,          // Move 100px along the x-axis
      rotation: 360,   // Rotate 360 degrees
      scale: 1.5,      // Scale the element by 1.5 times
      ease: "power2.out",  // Smooth easing
      delay: 0.5,      // Delay of 0.5 seconds before starting
      repeat: 2,       // Repeat the animation 2 times
      yoyo: true,      // Reverse after each repeat
      onComplete: () => console.log("Animation Completed!"), 
      // Fires on completion
    });
  }, []);

  return <div ref={boxRef} 
    style={{ width: 100, height: 100, backgroundColor: 'blue' }}>
    Animate Me</div>;
};

export default GsapComponent;

Example: GSAP Random Animation in React

import React, { useEffect, useRef } from "react";
import { gsap } from "gsap";

const RandomBoxes = () => {
  const boxesRef = useRef([]);

  useEffect(() => {
    boxesRef.current.forEach((box) => {
      gsap.to(box, {
        x: gsap.utils.random(0, 500),  // Random position between 0 and 500px for x
        y: gsap.utils.random(0, 300),  // Random position between 0 and 300px for y
        backgroundColor: gsap.utils.random(["#ff0000", "#00ff00", "#0000ff"]), // Random color
        duration: 2,
        repeat: -1,
        yoyo: true
      });
    });
  }, []);

  return (
    <div style={containerStyle}>
      <div
        className="box"
        ref={(el) => (boxesRef.current[0] = el)}
        style={boxStyle}
      ></div>
      <div
        className="box"
        ref={(el) => (boxesRef.current[1] = el)}
        style={boxStyle}
      ></div>
      <div
        className="box"
        ref={(el) => (boxesRef.current[2] = el)}
        style={boxStyle}
      ></div>
    </div>
  );
};

const containerStyle = {
  display: "flex",
  justifyContent: "space-around",
  alignItems: "center",
  height: "100vh",
};

const boxStyle = {
  width: "100px",
  height: "100px",
  backgroundColor: "red",
};

export default RandomBoxes;
1
Subscribe to my newsletter

Read articles from Vitthal Korvan directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Vitthal Korvan
Vitthal Korvan

๐Ÿš€ Hello, World! I'm Vitthal Korvan ๐Ÿš€ As a passionate front-end web developer, I transform digital landscapes into captivating experiences. you'll find me exploring the intersection of technology and art, sipping on a cup of coffee, or contributing to the open-source community. Life is an adventure, and I bring that spirit to everything I do.