visit
The design of the hook not only inherits the DX of the but also provides useful features and sugar events to us. Here are some examples to show you how does it work.
Basic Usage
Create an animation by the
keyframes
and animationOptions
options (these are the of the Element.animate()
).📦
import useWebAnimations from "@wellyshen/use-web-animations";
const App = () => {
const { ref, playState } = useWebAnimations({
keyframes: {
transform: "translateX(500px)", // Move by 500px
background: ["red", "blue", "green"], // Go through three colors
},
animationOptions: {
delay: 500, // Start with a 500ms delay
duration: 1000, // Run for 1000ms
iterations: 2, // Repeat once
direction: "alternate", // Run the animation forwards and then backwards
easing: "ease-in-out", // Use a fancy timing function
},
onReady: ({ playState, animate, animation }) => {
// Triggered when the animation is ready to play
},
onUpdate: ({ playState, animate, animation }) => {
// Triggered when the animation enters the running state or changes state
},
onFinish: ({ playState, animate, animation }) => {
// Triggered when the animation enters the finished state
},
// More useful options...
});
return (
<div className="container">
<p>🍿 Animation is {playState}</p>
<div className="target" ref={ref} />
</div>
);
};
Playback Control
The shortcoming with existing technologies was the lack of playback control. The Web Animations API provides several useful methods for controlling playback: play, pause, reverse, cancel, finish, seek, control speed via the of the Animation interface. This hook exposes the animation instance for us to interact with animations, we can access it by the
getAnimation()
return value.📦
import useWebAnimations from "@wellyshen/use-web-animations";
const App = () => {
const { ref, playState, getAnimation } = useWebAnimations({
playbackRate: 0.5, // Change playback rate, default is 1
autoPlay: false, // Automatically starts the animation, default is true
keyframes: { transform: "translateX(500px)" },
animationOptions: { duration: 1000, fill: "forwards" },
});
const play = () => {
getAnimation().play();
};
const pause = () => {
getAnimation().pause();
};
const reverse = () => {
getAnimation().reverse();
};
const cancel = () => {
getAnimation().cancel();
};
const finish = () => {
getAnimation().finish();
};
const seek = (e) => {
const animation = getAnimation();
const time = (animation.effect.getTiming().duration / 100) * e.target.value;
animation.currentTime = time;
};
const updatePlaybackRate = (e) => {
getAnimation().updatePlaybackRate(e.target.value);
};
return (
<div className="container">
<button onClick={play}>Play</button>
<button onClick={pause}>Pause</button>
<button onClick={reverse}>Reverse</button>
<button onClick={cancel}>Cancel</button>
<button onClick={finish}>Finish</button>
<input type="range" onChange={seek} />
<input type="number" defaultValue="1" onChange={updatePlaybackRate} />
<div className="target" ref={ref} />
</div>
);
};
Getting Animation's Information
When using the Web Animations API, we can get the information of an animation via the of the Animation interface. However, we can get the information of an animation by the
getAnimation()
return value as well.import useWebAnimations from "@wellyshen/use-web-animations";
const App = () => {
const { ref, getAnimation } = useWebAnimations({
keyframes: { transform: "translateX(500px)" },
animationOptions: { duration: 1000, fill: "forwards" },
});
const speedUp = () => {
const animation = getAnimation();
animation.updatePlaybackRate(animation.playbackRate * 0.25);
};
const jumpToHalf = () => {
const animation = getAnimation();
animation.currentTime = animation.effect.getTiming().duration / 2;
};
return (
<div className="container">
<button onClick={speedUp}>Speed Up</button>
<button onClick={jumpToHalf}>Jump to Half</button>
<div className="target" ref={ref} />
</div>
);
};
The animation instance isn't a part of , which means we need to access it by the
getAnimation()
whenever we need. If you want to monitor an animation's information, here's the onUpdate
event for you. The event is implemented by the internally and the event callback is triggered when the animation.playState
is running or changes.import { useState } from "react";
import useWebAnimations from "@wellyshen/use-web-animations";
const App = () => {
const [showEl, setShowEl] = useState(false);
const { ref } = useWebAnimations({
keyframes: { transform: "translateX(500px)" },
animationOptions: { duration: 1000, fill: "forwards" },
onUpdate: ({ animation }) => {
if (animation.currentTime > animation.effect.getTiming().duration / 2)
setShowEl(true);
},
});
return (
<div className="container">
{showEl && <div className="some-element" />}
<div className="target" ref={ref} />
</div>
);
};
Dynamic Interactions with Animation
We can create and play an animation at the
animationOptions
we want by the animate
method, which is implemented based on the . It's useful for interactions and the .Let's create a mouse interaction effect:📦
import { useEffect } from "react";
import useWebAnimations from "@wellyshen/use-web-animations";
const App = () => {
const { ref, animate } = useWebAnimations();
useEffect(() => {
document.addEventListener("mousemove", (e) => {
// The target will follow the mouse cursor
animate({
keyframes: { transform: `translate(${e.clientX}px, ${e.clientY}px)` },
animationOptions: { duration: 500, fill: "forwards" },
});
});
}, [animate]);
return (
<div className="container">
<div className="target" ref={ref} />
</div>
);
};
import useWebAnimations from "@wellyshen/use-web-animations";
const App = () => {
const { ref, animate } = useWebAnimations({
id: "fall", // Set animation id, default is empty string
keyframes: [{ top: 0, easing: "ease-in" }, { top: "500px" }],
animationOptions: { duration: 300, fill: "forwards" },
onFinish: ({ animate, animation }) => {
// Lifecycle is triggered by each animation, we can check the id to prevent animation from repeating
if (animation.id === "bounce") return;
animate({
id: "bounce",
keyframes: [
{ top: "500px", easing: "ease-in" },
{ top: "10px", easing: "ease-out" },
],
animationOptions: { duration: 300, composite: "add" },
});
},
});
return (
<div className="container">
<div className="target" ref={ref} />
</div>
);
};
⚠️ Composite modes isn't fully supported by all the browsers, please check the carefully before using it.
import useWebAnimations, { bounce } from "@wellyshen/use-web-animations";
const App = () => {
// Add a pre-defined effect to the target
const { ref } = useWebAnimations({ ...bounce });
return (
<div className="container">
<div className="target" ref={ref} />
</div>
);
};
const { keyframes, animationOptions } = bounce;
const { ref } = useWebAnimations({
keyframes,
animationOptions: {
...animationOptions,
delay: 1000, // Delay 1s
duration: animationOptions.duration * 0.75, // Speed up the animation
},
});
$ yarn add @wellyshen/use-web-animations
# or
$ npm install --save @wellyshen/use-web-animations