Have you ever created a page and felt like it lacks the SAUCE? In my opinion, that drip usually comes from micro-interactions (small interactions with the sole purpose of delighting users). There are many libraries around for creating them, but my favorite one is GSAP, which allows creating performant and complex animations easily.
When using GSAP with React, however, the integration doesn't feel right: creating a Tween/Timeline and storing it in a React.useRef()
, adding .to()
's and .from()
's inside a React.useEffect()
looks strange to me. This is needed in order to prevent re-declaring on every render, which would re-trigger animations every time something changes in the DOM tree.
This is where SolidJS is brought into play. It looks like React, but has a main difference. according to its documentation:
Every Component executes once and it is the Hooks and bindings that execute many times as their dependencies update.
This means no useRef
needed for storing a timeline. In Solid you may simply declare it like this:
const tl = gsap.timeline({paused: true});
And it won't be re-declared on every render. Very cool, eh? This approach is useful for most libraries thatinteract with the DOM to add transitions and animations (ScrollReveal.js, for example).
Animating with GSAP in Solid.js
When adding an animation to a timeline, GSAP needs to know which element should be animated. This can be done using an element reference. There are two ways of getting a ref in Solid:
- Pass a ref variable to a JSX element and add the animation inside
onMount
:
let containerRef;
onMount(() => {
gsap.to(containerRef, {
// TODO: animation
});
});
return <div ref={containerRef} />;
- Or, my favorite one, using custom directives:
const animation = (element) => {
// code goes here
};
return <div use:animation />;
Custom directives are syntax sugar over ref, which allows us to easily attach multiple directives to a single element. A directive is a function that receives an Element and an Accessor as arguments, that looks like this:
const hoverAnimation = (el, _accessor) => {
const animation = gsap.to(el, {
// properties
});
el.addEventListener("mouseenter", () => {
animation.play();
});
el.addEventListener("mouseleave", () => {
animation.pause();
});
};
And may then be added to any element like this:
const App () => (
<div use:hoverAnimation />
<div use:hoverAnimation />
);
An element can have multiple directives, and a directive can be used in multiple elements, making it possible to create GSAP animations that can be re-used throughout your app.
Check out this live demo of an object that changes it background color on hover:
Top comments (4)
Nice modification of the gsap character to have solid theme, did you design it?
Thanks!! Yea, I made it in Illustrator, haha
this is great, thanks!
Nice one.. the directives use, I mean. Clever and simple. Thanx ! Its definitely all about that drip of sauce lol