GithubHelp home page GithubHelp logo

wellyshen / use-web-animations Goto Github PK

View Code? Open in Web Editor NEW
1.3K 7.0 29.0 3.7 MB

๐Ÿ˜Ž ๐Ÿฟ React hook for highly-performant and manipulable animations using Web Animations API.

Home Page: https://use-web-animations.netlify.app

License: MIT License

TypeScript 86.94% JavaScript 3.19% Shell 0.14% HTML 3.32% SCSS 6.40%
react hook animation web-animations web-animations-api use-web-animations waapi playback-control motion performance

use-web-animations's Introduction

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 gzip size 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.

โš ๏ธ Most modern browsers support Web Animations API natively. You can also use polyfill for full browser support.

Basic Usage

Create an animation by the keyframes and animationOptions options (these are the parameters of the Element.animate()).

๐Ÿ’ก This hook supports the pseudoElement property via the animationOptions option.

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
    },
    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>
  );
};

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");
      }
    },
  });

  // ...
};

Setting/Updating Animation

The keyframes and animationOptions are cached when the hook is mounted. However, we can set/update the animation by the animation method.

const { animation } = useWebAnimations();

const changeAnim = () =>
  animation({
    keyframes: { transform: ["translateX(0)", "translateX(100px)"] },
    animationOptions: 1000,
    id: "123",
    playbackRate: 1,
    autoPlay: true,
  });

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)" },
    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 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)" },
    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 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)" },
    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 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)` },
        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 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, animationOptions } = bounce;
const { ref } = useWebAnimations({
  keyframes,
  animationOptions: {
    ...animationOptions,
    delay: 1000, // Delay 1s
    duration: animationOptions.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 });

Working in TypeScript

This hook supports TypeScript, you can tell the hook what type of element you are going to animate through the generic type:

const App = () => {
  const { ref } = useWebAnimations<HTMLDivElement>();

  return <div ref={ref} />;
};

๐Ÿ’ก For more available types, please check it out.

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 | undefined Describes the playback state of an animation.
getAnimation function Access the animation instance for playback control, animation's information and more.
animate function Imperatively set/update the animation. 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 An array of keyframe objects, or a keyframe object whose property are arrays of values to iterate over. See basic usage for more details.
animationOptions number | object An integer representing the animation's duration (in milliseconds), or an object containing one or more timing properties. See basic usage 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.
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.

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.

Articles / Blog Posts

๐Ÿ’ก If you have written any blog post or article about use-web-animations, please open a PR to add it here.

Contributors โœจ

Thanks goes to these wonderful people (emoji key):


Welly

๐Ÿ’ป ๐Ÿ“– ๐Ÿšง

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

use-web-animations's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

use-web-animations's Issues

The hook die when I try to use 'onFinish' property function

Bug Report

Describe the Bug

I'm try to make a sidebar slider and I need to know when is the animation finished. I'm using the property 'onFinish' and the browser trown an error saying 'Can't read property then of undefined'. I'm using next.js by the way.
Your library is awesome!

Screenshots

image

Animate array of refs to move hundreds of elements with one animation definition

Feature Request

Describe the Feature

Hi! I'm trying to animate something like confetti falling down seen here. In order to get this to work I want to animate hundreds of small divs, with small variations between the animations.

Describe the Solution You'd Like

If I have something like this in my component:

const {pushToRefs, getAnimations} = useWebAnimationGroup((index) => {...confettiFalling(index)})
// confettiFalling returns slightly different parameters for each index
return <>
  {[...Array(1000).keys()].map(key => (
    // pushToRefs registers each div in an array and runs the function provided to the hook for each one.
    <div className="confetti-particle" key={item} ref={pushToRefs}/>
  ))
</>

Then I'd like to be able to pause/reverse all of the animations as if they were one

const handlePause = () => getAnimations().pause()

Describe Alternatives You've Considered

I could maybe get it t work with a HOC which calls the use web animation hook internally, and provides a prop for play state, and have the HOC use useEffect to react to the changes. It would be a bit cumbersome maybe, but it can probably work fine for my usecase.

Pseudo Element Animation Support

Feature Request

Describe the Feature

Adding a pseudo element attribute to the options object - similar to the actual native api

Ex: https://css-tricks.com/pseudo-elements-in-the-web-animations-api/

Describe the Solution You'd Like

When instantiating a new web animations object, there should be an option to define a pseudo element you'd like to target

const { ref, playState } = useWebAnimations({
    keyframes: {
      transform: "translateX(500px)", 
      background: ["red", "blue", "green"], 
    },
    timing: {
      delay: 500, 
      duration: 1000, 
      iterations: 2, 
      direction: "alternate", 
      easing: "ease-in-out", 
    },
    pseudoElement: '::after', // NOTE: this flag here would be added
    // ... More useful options ...
  });

Describe Alternatives You've Considered

I don't think there is another way to handle this? The only alternative is to animate another element and change the markup to work well with the added element

Additional Information

Example of why this is useful:

An example where this comes up is when trying to create toast messages after clicking on an element

For example - this toast message after clicking on a copy to clipboard button is often just a pseudo element:

image

So being able to keep the styling for this toast message inside the pseudo element CSS, while being able to express animation logic with useWebAnimations.

Example with Higher Order Component

Feature Request

I'm trying to find a way to make an animation with your hook reusable in a High Order Component. It may be my confusion around ref, but I would be interested to see if you have an example of use-web-animations in an HOC

Additional Information

Following up on my question on Twitter ๐Ÿ˜

No way to cancel animation state updates on an unmounted component

Bug Report

Describe the Bug

There appears to be no canceling of the animation when the component unmounts. onFinished will still fire, even if the component has been removed from the DOM by React. The internals of use-web-animation also perform state updates during the animation cycle, which causes a warning from react.

How to Reproduce

  1. Go to the code sandbox link below
  2. Watch the console
  3. After 2 seconds you will see the typical react error:
Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
JustWaitAnim@https://zzit3.csb.app/src/App.js:27:58

I've traced this into the code, and I believe the warning originates from checking then setting the animation state:

if (prevPlayStateRef.current !== curPlayState)
setPlayState(curPlayState);
.

CodeSandbox Link

Codesandbox link: https://codesandbox.io/s/use-web-animations-no-state-unmounted-component-bug-zzit3?file=/src/App.js

Expected Behavior

Personally, I didn't expect the onFinish callback to fire if unmounted! But I understand why it does. Mostly, I don't think the hook should trigger React warnings.

I see a few possibilities:

  1. prevent checking for animation state if the component unmounts
  2. cancel animations when the component unmounts (a new feature? canceling animations seems non-trivial to prevent thrown exceptions: https://developer.mozilla.org/en-US/docs/Web/API/Animation/cancel#exceptions)
  3. provide a flag option (autocancel?) that will call animation.cancel(), as well as cancel any checking and callback execution.

I ran into this bug because I was controlling the autoplay option with a component property. This actually resulted in the animation running twice! It took me several hours before I found the issue: use-web-animations uses these values to know whether to apply the animation. Thus, it assumed that it was a new animation configuration and should be applied. I was using the onFinish callbacks to trigger logic updates, which caused many bugs due to firing twice!

Additional Information

Thank you for making use-web-animations! I think it's a really neat library!

Typescript types don't include animation presets

Bug Report

Describe the Bug

A clear and concise description of what the bug is.

The Typescript types in index.d.ts don't define the huge list of (incredibly useful) preset animations. For example, when importing the fadeOut preset:

import useWebAnimations, { fadeOut } from '@wellyshen/use-web-animations';

I get the following error (even though fadeOut is exported by index.js... it's just not defined in index.d.ts so Typescript doesn't pick it up):

Module '"@wellyshen/use-web-animations"' has no exported member 'fadeOut'. Did you mean to use 'import fadeOut from "@wellyshen/use-web-animations"' instead?

How to Reproduce

Steps to reproduce the behavior, please provide code snippets or a repository:

  1. Create a Typescript project and import an animation preset.
  2. Try to compile (or just run ESLint).
  3. See error.

Expected Behavior

To fix this, merely add all of those animation presets as exported constants to your index.d.ts (this will be quite tedious... you should probably look into a better way to do this perhaps).

"onFinish" does not work with vite 3.0 dev mode

Bug Report

Describe the Bug

The latest vite3.0 & React will trigger unmount forcibly at the first render.
This behavior causes hasUnmountedRef.current === true. The related code is as below.

        if (!hasUnmountedRef.current) {
          // @ts-expect-error
          onFinishRef.current({
            playState: animation.playState,
            animate: animate,
            animation: animation
          });
        }

How to Reproduce

  1. Launch vite example project
  2. Copy the below code
import { useState } from "react";
import reactLogo from "./assets/react.svg";
import "./App.css";
import useWebAnimations from "@wellyshen/use-web-animations";

function App() {
  const [count, setCount] = useState(0);
  const { animate, ref, playState, getAnimation } = useWebAnimations({
    onFinish: ({ animation }) => {
      console.warn("onFinish");
    },
  });

  return (
    <div className="App">
      <div className="card">
        <button
          onClick={() => {
            animate({
              keyframes: [
                { transform: `scale(1.08)`, offset: 0 },
                { transform: `scale(1)`, offset: 150 / 500.0 },
                { transform: `scale(1.08)`, offset: 1 },
              ],
              animationOptions: {
                duration: 500,
                easing: "cubic-bezier(0.3,0,0.15,1)",
              },
            });
            setCount((count) => count + 1);
          }}
          ref={ref}
        >
          count is {count}, {playState}
        </button>
      </div>
    </div>
  );
}

export default App;

Expected Behavior

"onFinish" should be triggered

Your Environment

  • Browser: [e.g. Chrome]
  • Version: [e.g. v105]

Animation loops before finishing when using dynamic keyframes

Bug Report

Describe the Bug

I have tried creating a HOC with an animated box, which has slightly different animations depending on Math.random(), the animation should run once and finish, but for some reason it keeps looping and each box finishes animating after a random amount of iteration.

How to Reproduce

import "./styles.css";
import useWebAnimations from "@wellyshen/use-web-animations";

export default function App() {
  return (
    <div className="container">
      {[...Array(5).keys()].map((key) => (
        <AnimatedBox key={key} />
      ))}
    </div>
  );
}

const AnimatedBox = () => {
  const { ref } = useWebAnimations({
    keyframes: [{ top: "0%" }, { top: Math.random() > 0.5 ? "50%" : "100%" }],
    animationOptions: {
      duration: 1000,
      fill: "forwards"
    }
  });

  return <div className="box" ref={ref} />;
};

styles are only for the flex container and to get the boxes to have size, background, and position relative.

CodeSandbox Link

Here's a codesandbox with the issue

Expected Behavior

I expect the animation to be calculated once the first time the hook runs, then be executed, and finish, instead of looping.

Your Environment

  • Device: Lenovo Ideapad
  • OS: Linux
  • Browser: Both Chrome and Firefox tested
  • Version: 0.7.4

Additional Information

Placing the arguments inside a ref and using that fixes the looping:

const AnimatedBox = () => {
  const options = useRef({
    keyframes: [{ top: "0%" }, { top: Math.random() > 0.5 ? "50%" : "100%" }],
    animationOptions: {
      duration: 1000,
      fill: "forwards"
    }
  });
  const { ref } = useWebAnimations(options.current);

  return <div className="box" ref={ref} />;
};

Should the hook do this internally? Or should this workaround be added to the doc?

onFinish is only called after first finishing an animation

Bug Report

Describe the Bug

I'm trying to use the onFinish callback, together with controlling play status. After the animation finishes for the first time, the onFinish callback will be called, but not on subsequent calls.

How to Reproduce

Add an onFinish handler, start the animation with getAnimation().play() twice.

CodeSandbox Link

Bug example.

Expected Behavior

onFinish should be called whenever playState switches from 'running' to 'finished'

Your Environment

  • Device: Lenovo thinkpad
  • OS: Manjaro Linux
  • Browser: Both Chrome and Firefox tested.
  • Version: Both 0.9, and 0.7.4 show this behavior. I have not tested 0.8, should

Built-in animations of "Animate CSS" aren't working in version 6.

Recently I was working on a project. I had installed version 0.6 and there was an error that "bounce is not exported from @wellyshen/use-web-animations". Then I installed version 0.5.11 and it was working then.

Hope my issue will be helpful in solving the problem.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.