const { useEffect, useLayoutEffect, useRef, forwardRef, useState } = React;
gsap.registerPlugin(CustomEase, CustomWiggle);
gsap.config({ trialWarn: false });
CustomWiggle.create("myWiggle", {
wiggles: 8,
type: "uniform"
});
gsap.registerEffect({
name: "pulse",
effect(targets) {
return gsap.fromTo(targets, {
scale: 1
}, {
scale: 1.5,
repeat: 1,
ease: "bounce",
yoyoEase: "power3"
});
}
});
gsap.registerEffect({
name: "spin",
effect(targets) {
return gsap.to(targets, {
rotation: (i, el) => gsap.utils.snap(360, gsap.getProperty(el, "rotation") + 360)
});
}
});
gsap.registerEffect({
name: "shake",
effect(targets) {
return gsap.fromTo(targets, {
x: 0
}, {
x: 10,
ease: "myWiggle"
});
}
});
function useGsapEffect(target, effect, vars) {
const [animation, setAnimation] = useState();
useLayoutEffect(() => {
if (gsap.effects[effect]) {
setAnimation(gsap.effects[effect](target.current, vars));
}
}, [effect, target, vars]);
return animation;
}
const Box = forwardRef(({ children }, ref) => {
return <div className="box gradient-blue" ref={ref}>{children}</div>;
});
const wrap = gsap.utils.wrap(["pulse", "spin", "shake"]);
function App() {
const boxRef = useRef();
const count = useRef(0);
const [effect, setEffect] = useState("");
const animation = useGsapEffect(boxRef, effect);
const toggle = () => {
setEffect(wrap(count.current++));
};
return (
<div className="app">
<div>
<button onClick={toggle}>Toggle</button>
</div>
<p>Effect: {effect}</p>
<Box ref={boxRef}>Box</Box>
</div>
);
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
View Compiled