Skip to content

Creating a Magnetic Effect Using GSAP in Next.js

Posted on:May 18, 2024 at 08:12 PM

Web animations can significantly enhance user experience, making interfaces more interactive and engaging. In this post, we’ll walk through creating a magnetic animation effect using GreenSock Animation Platform (GSAP) in a nextjs component. This animation makes an element follow the user’s cursor with an elastic motion, creating a magnetic effect.

Table of contents

Open Table of contents

Setting Up Your Project

Before we dive into the code, ensure you have a nextjs project set up. You can create a new nextjs project using Create Nextjs:

npx create-next-app@latest magnetic-effect
cd magnetic-effect

Next, install GSAP:

npm install gsap 

Creating the Magnetic Effect Component

Now Create a new component file, Magnetic.jsx, and follow Step-by-Step.

Importing Dependencies

First, we import the necessary dependencies from React and GSAP:

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

Creating the Magnetic Component

We define the Magnetic component, which takes children as props. This allows us to wrap any element with the magnetic effect.

export default function Magnetic({ children }) {
    const magnetic = useRef(null);

We use the useRef hook to create a reference to the DOM element that will have the magnetic effect.

Setting Up GSAP Animations

Inside the useEffect hook, we define the GSAP animations:

useEffect(() => {
    const xTo = gsap.quickTo(magnetic.current, "x", { duration: 1, ease: "elastic.out(1, 0.3)" });
    const yTo = gsap.quickTo(magnetic.current, "y", { duration: 1, ease: "elastic.out(1, 0.3)" });

The gsap.quickTo function creates quick setters for the x and y properties with a duration of 1 second and an elastic easing effect.

Handling Mouse Events

Next, we add event listeners for mousemove and mouseleave:

magnetic.current.addEventListener("mousemove", (e) => {
    const { clientX, clientY } = e;
    const { height, width, left, top } = magnetic.current.getBoundingClientRect();
    const x = clientX - (left + width / 2);
    const y = clientY - (top + height / 2);
    xTo(x * 0.35);
    yTo(y * 0.35);
});

magnetic.current.addEventListener("mouseleave", () => {
    xTo(0);
    yTo(0);
});

Returning the Element

Finally, we use React.cloneElement to attach the ref to the child element:

return React.cloneElement(children, { ref: magnetic });
}

Using the Magnetic Component

To use the Magnetic component, wrap any element you want to have the magnetic effect:

import React from 'react';
import Magnetic from './Magnetic';

function App() {
    return (
        <div className="App">
            <Magnetic>
                <button className="magnetic-button">Hover over me!</button>
            </Magnetic>
        </div>
    );
}

export default App;

Here is final Code:

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

export default function Magnetic({ children }) {
    const magnetic = useRef(null);

    useEffect(() => {
        const xTo = gsap.quickTo(magnetic.current, "x", { duration: 1, ease: "elastic.out(1, 0.3)" });
        const yTo = gsap.quickTo(magnetic.current, "y", { duration: 1, ease: "elastic.out(1, 0.3)" });

        magnetic.current.addEventListener("mousemove", (e) => {
            const { clientX, clientY } = e;
            const { height, width, left, top } = magnetic.current.getBoundingClientRect();
            const x = clientX - (left + width / 2);
            const y = clientY - (top + height / 2);
            xTo(x * 0.35);
            yTo(y * 0.35);
        });

        magnetic.current.addEventListener("mouseleave", () => {
            xTo(0);
            yTo(0);
        });
    }, []);

    return React.cloneElement(children, { ref: magnetic });
}

Conclusion

By following this guide, you’ve created a magnetic animation effect using GSAP. This effect adds a layer of interactivity to your elements, making them more engaging for users. Experiment with different easing effects and durations to achieve the desired feel for your animations. Happy coding!