All Projects β†’ wellyshen β†’ Use Web Animations

wellyshen / Use Web Animations

Licence: mit
😎 🍿 React hook for highly-performant and manipulable animations using Web Animations API.

Programming Languages

typescript
32286 projects

Projects that are alternatives of or similar to Use Web Animations

use-spring
Hooke's law hook
Stars: ✭ 53 (-93.39%)
Mutual labels:  hook, motion, transition
React Intersection Observer
React implementation of the Intersection Observer API to tell you when an element enters or leaves the viewport.
Stars: ✭ 2,689 (+235.29%)
Mutual labels:  hook, performance
React Cool Inview
😎 πŸ–₯️ React hook to monitor an element enters or leaves the viewport (or another element).
Stars: ✭ 830 (+3.49%)
Mutual labels:  hook, performance
react-transition-state
Zero dependency React transition state machine.
Stars: ✭ 239 (-70.2%)
Mutual labels:  hook, transition
Personal Goals
List of books I've read, projects I've done, videos I've seen, articles I've read or podcasts I've listened to.
Stars: ✭ 75 (-90.65%)
Mutual labels:  performance, ux
Web Vitals Extension
A Chrome extension to measure essential metrics for a healthy site
Stars: ✭ 1,943 (+142.27%)
Mutual labels:  performance, ux
ReactZooApp
ReactZooApp
Stars: ✭ 33 (-95.89%)
Mutual labels:  ux, motion
Anix
🐿 Super easy and lightweight(<3kb) JavaScript animation library
Stars: ✭ 239 (-70.2%)
Mutual labels:  transition, motion
ux-lab
No description or website provided.
Stars: ✭ 49 (-93.89%)
Mutual labels:  ux, transition
AniX
🐿 Super easy and lightweight(<3kb) JavaScript animation library
Stars: ✭ 253 (-68.45%)
Mutual labels:  motion, transition
React Magic Hat
🎩✨Library to implement the Magic Hat technique, blazingly fast πŸš€
Stars: ✭ 297 (-62.97%)
Mutual labels:  ux, motion
Shiny
Shiny uses your gyroscope to simulate lighting and motion effects on colors. Works on almost every SwiftUI View.
Stars: ✭ 226 (-71.82%)
Mutual labels:  ux, motion
Pixelwave
Fully customizable pixel wave animation for seamless page transitions.
Stars: ✭ 119 (-85.16%)
Mutual labels:  ux, transition
Medium Zoom
πŸ”ŽπŸ–Ό A JavaScript library for zooming images like Medium
Stars: ✭ 2,799 (+249%)
Mutual labels:  performance, ux
Easytransitions
A simple way to create custom interactive UIViewController transitions
Stars: ✭ 1,592 (+98.5%)
Mutual labels:  ux, transition
React Cool Dimensions
😎 πŸ“ React hook to measure an element's size and handle responsive components.
Stars: ✭ 419 (-47.76%)
Mutual labels:  hook, performance
Element Motion
Tween between view states with declarative zero configuration element motions for React
Stars: ✭ 828 (+3.24%)
Mutual labels:  transition, motion
Droidmotion
πŸ‚ Implementation of a simple android motion
Stars: ✭ 200 (-75.06%)
Mutual labels:  transition, motion
SPLarkController
Custom transition between controllers. Settings controller for your iOS app.
Stars: ✭ 967 (+20.57%)
Mutual labels:  ux, transition
Vue Motion
Easy and natural state transitions
Stars: ✭ 373 (-53.49%)
Mutual labels:  transition, motion

USE-WEB-ANIMATIONS

Using Web Animations API (a.k.a WAAPI) in the React hook way. Let's create highly-performant, flexible and manipulable web animations in the modern world. Hope you guys πŸ‘πŸ» it!

❀️ it? ⭐️ it on GitHub or Tweet about it.

build status coverage status npm version npm downloads npm downloads npm bundle size MIT licensed All Contributors PRs welcome Twitter URL

demo_basic

⚑️ Try yourself: https://use-web-animations.netlify.app

demo_animate

⚑️ Try yourself: https://use-web-animations.netlify.app#animations

Features

Requirement

To use use-web-animations, you must use [email protected] or greater which includes hooks.

Installation

This package is distributed via npm.

$ yarn add @wellyshen/use-web-animations
# or
$ npm install --save @wellyshen/use-web-animations

Before We Start

With the Web Animations API, we can move interactive animations from stylesheets to JavaScript, separating presentation from behavior. The API was designed based on the concept of the CSS Animations but there're still some differences between them. I strongly recommend you to read the documentation before we dive into this hook.

Usage

The API design of the hook not only inherits the DX of the Web Animations API but also provides useful features and sugar events to us. Here are some examples to show you how does it work.

⚠️ polyfill for full browser support.

Basic Usage

Create an animation by the keyframes (formats) and timing (properties) options.

Edit useWebAnimations - basic

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
    },
    timing: {
      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 (Google Chrome: available in v84+)
    },
    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 (Google Chrome: available in v84+)
    },
    // More useful options...
  });

  return (
    <div className="container">
      <p>🍿 Animation is {playState}</p>
      <div className="target" ref={ref} />
    </div>
  );
};

For browsers that don't yet support the onReady and onFinish events, we can use the onUpdate to monitor the animation's state instead.

let prevPending = true;

const App = () => {
  const { ref } = useWebAnimations({
    // ...
    onUpdate: ({ playState, animation: { pending } }) => {
      if (prevPending && !pending) {
        console.log("Animation is ready to play");
      }
      prevPending = pending;

      if (playState === "finished") {
        console.log("Animation has finished playing");
      }
    },
  });

  // ...
};

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 methods 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.

Edit useWebAnimations - controls

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)" },
    timing: { 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 properties 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)" },
    timing: { 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 React state, 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 requestAnimationFrame internally and the event callback is triggered when the animation enters running state or changes state.

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)" },
    timing: { 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 timing we want by the animate() return value, which is implemented based on the Element.animate(). It's useful for interactions and the composite modes.

Let's create a mouse interaction effect:

Edit useWebAnimations - interaction

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)` },
        timing: { 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" }],
    timing: { 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" },
        ],
        timing: { 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 browser compatibility 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 Animate.css.

πŸ‘‰πŸ» Check out the demo.

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, timing } = bounce;
const { ref } = useWebAnimations({
  keyframes,
  timing: {
    ...timing,
    delay: 1000, // Delay 1s
    duration: timing.duration * 0.75, // Speed up the animation
  },
});
See all available animations

Attention seekers

  • bounce
  • flash
  • pulse
  • rubberBand
  • shakeX
  • shakeY
  • headShake
  • swing
  • tada
  • wobble
  • jello
  • heartBeat

Back entrances

  • backInDown
  • backInLeft
  • backInRight
  • backInUp

Back exits

  • backOutDown
  • backOutLeft
  • backOutRight
  • backOutUp

Bouncing entrances

  • bounceIn
  • bounceInDown
  • bounceInLeft
  • bounceInRight
  • bounceInUp

Bouncing exits

  • bounceOut
  • bounceOutDown
  • bounceOutLeft
  • bounceOutRight
  • bounceOutUp

Fading entrances

  • fadeIn
  • fadeInDown
  • fadeInDownBig
  • fadeInLeft
  • fadeInLeftBig
  • fadeInRight
  • fadeInRightBig
  • fadeInUp
  • fadeInUpBig
  • fadeInTopLeft
  • fadeInTopRight
  • fadeInBottomLeft
  • fadeInBottomRight

Fading exits

  • fadeOut
  • fadeOutDown
  • fadeOutDownBig
  • fadeOutLeft
  • fadeOutLeftBig
  • fadeOutRight
  • fadeOutRightBig
  • fadeOutUp
  • fadeOutUpBig
  • fadeOutTopLeft
  • fadeOutTopRight
  • fadeOutBottomLeft
  • fadeOutBottomRight

Flippers

  • flip
  • flipInX
  • flipInY
  • flipOutX
  • flipOutY

Lightspeed

  • lightSpeedInRight
  • lightSpeedInLeft
  • lightSpeedOutRight
  • lightSpeedOutLeft

Rotating entrances

  • rotateIn
  • rotateInDownLeft
  • rotateInDownRight
  • rotateInUpLeft
  • rotateInUpRight

Rotating exits

  • rotateOut
  • rotateOutDownLeft
  • rotateOutDownRight
  • rotateOutUpLeft
  • rotateOutUpRight

Specials

  • hinge
  • jackInTheBox
  • rollIn
  • rollOut

Zooming entrances

  • zoomIn
  • zoomInDown
  • zoomInLeft
  • zoomInRight
  • zoomInUp

Zooming exits

  • zoomOut
  • zoomOutDown
  • zoomOutLeft
  • zoomOutRight
  • zoomOutUp

Sliding entrances

  • slideInDown
  • slideInLeft
  • slideInRight
  • slideInUp

Sliding exits

  • slideOutDown
  • slideOutLeft
  • slideOutRight
  • slideOutUp

Use Your Own ref

In case of you had a ref already or you want to share a ref for other purposes. You can pass in the ref instead of using the one provided by this hook.

const ref = useRef();
const { playState } = useWebAnimations({ ref });

API

const returnObj = useWebAnimations(options?: object);

Return Object

It's returned with the following properties.

Key Type Default Description
ref object Used to set the target element for animating.
playState string Describes the playback state of an animation.
getAnimation function Access the playback control, animation's information and more.
animate function Creates animation at the timing you want. Useful for interactive animations and composite animations.

Parameter

The options provides the following configurations and event callbacks for you.

Key Type Default Description
ref object For some reasons, you can pass in your own ref instead of using the built-in.
id string "" Sets the ID of an animation, implemented based on the Animation.id.
playbackRate number 1 Sets the playback rate of an animation, implemented based on the Animation.playbackRate.
autoPlay boolean true Automatically starts the animation.
keyframes Array | object Describes sets of animatable properties and values, similar to CSS @keyframes but slightly different. See Keyframe Formats for more details.
timing number | object Describes timing properties for animation effects. See EffectTiming for more details.
onReady function It's invoked when an animation is ready to play. You can access the playState, animate and animation from the event object. (Google Chrome: available in v84+)
onUpdate function It's invoked when an animation enters the running state or changes state. You can access the playState, animate and animation from the event object.
onFinish function It's invoked when an animation enters the finished state. You can access the playState, animate and animation from the event object. (Google Chrome: available in v84+)

Use Polyfill

Web Animations API has good support amongst browsers, but it's not universal. You'll need to polyfill browsers that don't support it. Polyfills is something you should do consciously at the application level. Therefore use-web-animations doesn't include it.

Install web-animations-js:

$ yarn add web-animations-js
# or
$ npm install --save web-animations-js

Then import it at your app's entry point:

import "web-animations-js/web-animations.min";

You can read the document for more information.

Contributors ✨

Thanks goes to these wonderful people (emoji key):

🚧

This project follows the all-contributors specification. Contributions of any kind welcome!

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].