paint-brush
Creating Highly-Performant Animations using Web Animations API and React hooks  by@welly
10,306 reads
10,306 reads

Creating Highly-Performant Animations using Web Animations API and React hooks

by wellyJuly 4th, 2020
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

Using Web Animations API and React hooks, we can create highly-performant, flexible and manipulable web animations in the modern world. The API design of the hook inherits the DX of the Web Animation API but also provides useful features and sugar events to us. The hook exposes the animation instance for us to interact with animations. This hook exposes animation instance to us by the React hook value. Play on CodeSandbox or use useWebAnimations from "@wellyshen/use-web-animations"

Companies Mentioned

Mention Thumbnail
Mention Thumbnail
featured image - Creating Highly-Performant Animations using Web Animations API and React hooks
welly HackerNoon profile picture
Using  (a.k.a WAAPI) in the React  way. Let's create highly-performant, flexible and manipulable web animations in the modern world. Hope you guys 👍🏻 it!
⚡️ Try yourself: 
⚡️ Try yourself: 

Features

  • 🚀 Animate on the Web with highly-performant and manipulable way, using .
  • 🎣 Easy to use, based on React .
  • 🎛 Super flexible  design that can cover  that you need.
  • 🎞  for you, based on .
  • 🔩 Supports custom refs for .
  • 📜 Supports  type definition.
  • 🗄️ Server-side rendering compatibility.
  • 🦔 Tiny size (). No external dependencies, aside for the `react`.

Usage

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>
  );
};
Create a bounce effect via lifecycle and composite mode:
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.

Use Built-in Animations

Too lazy to think about animation? We provide a collection of ready-to-use animations for you, they are implemented based on .👉🏻 
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>
  );
};
We can customize the built-in animation by overriding its properties:
const { keyframes, animationOptions } = bounce;
const { ref } = useWebAnimations({
  keyframes,
  animationOptions: {
    ...animationOptions,
    delay: 1000, // Delay 1s
    duration: animationOptions.duration * 0.75, // Speed up the animation
  },
});

Thanks for reading, for more usage details checkout the project's GitHub page: You can also install this package is distributed via .
$ yarn add @wellyshen/use-web-animations
# or
$ npm install --save @wellyshen/use-web-animations
바카라사이트 바카라사이트 온라인바카라