Skip to content

Commit

Permalink
Merge e7dbaa2 into 5c57418
Browse files Browse the repository at this point in the history
  • Loading branch information
wellyshen committed Jul 3, 2020
2 parents 5c57418 + e7dbaa2 commit 5060dbe
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 23 deletions.
26 changes: 25 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,30 @@ const App = () => {
};
```

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

```js
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](https://developer.mozilla.org/en-US/docs/Web/API/Animation#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.
Expand Down Expand Up @@ -205,7 +229,7 @@ const App = () => {
};
```

The animation instance isn't a part of [React state](https://reactjs.org/docs/hooks-state.html), 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](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame) internally and the event callback is triggered when the `animation.playState` is running or changes.
The animation instance isn't a part of [React state](https://reactjs.org/docs/hooks-state.html), 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](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame) internally and the event callback is triggered when the animation enters `running` state or changes state.

```js
import React, { useState } from "react";
Expand Down
58 changes: 36 additions & 22 deletions src/useWebAnimations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import useLatest from "./useLatest";

if (typeof window !== "undefined") loadPolyfill();

const errorMsg = (type: string) =>
`> 💡use-web-animations: the browser doesn't support ${type} event, please use onUpdate to monitor the animation's state instead. See https://github.com/wellyshen/use-web-animations#basic-usage`;

type Keyframes = Keyframe[] | PropertyIndexedKeyframes;
type PlayState = string | null;
interface AnimConf {
Expand Down Expand Up @@ -52,6 +55,7 @@ const useWebAnimations = <T extends HTMLElement>({
}: Options<T> = {}): Return<T> => {
const [playState, setPlayState] = useState<PlayState>(null);
const animRef = useRef<Animation>();
const prevPendingRef = useRef<boolean>();
const prevPlayStateRef = useRef<string>();
const onReadyRef = useLatest<Callback>(onReady);
const onUpdateRef = useLatest<Callback>(onUpdate);
Expand All @@ -71,22 +75,34 @@ const useWebAnimations = <T extends HTMLElement>({
if (args.autoPlay === false) anim.pause();
if (args.id) anim.id = args.id;
if (args.playbackRate) anim.playbackRate = args.playbackRate;
if (onReadyRef.current)
anim.ready.then((animation) => {
onReadyRef.current({
playState: animation.playState,
animate,
animation,

if (onReadyRef.current) {
if (anim.ready) {
anim.ready.then((animation) => {
onReadyRef.current({
playState: animation.playState,
animate,
animation,
});
});
});
if (onFinishRef.current)
anim.finished.then((animation) => {
onFinishRef.current({
playState: animation.playState,
animate,
animation,
} else {
console.error(errorMsg("onReady"));
}
}

if (onFinishRef.current) {
if (anim.finished) {
anim.finished.then((animation) => {
onFinishRef.current({
playState: animation.playState,
animate,
animation,
});
});
});
} else {
console.error(errorMsg("onFinish"));
}
}

prevPlayStateRef.current = undefined;
},
Expand All @@ -103,22 +119,20 @@ const useWebAnimations = <T extends HTMLElement>({
const animation = getAnimation();

if (animation) {
const { playState: curPlayState } = animation;
const { pending, playState: curPlayState } = animation;

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

if (
onUpdateRef.current &&
(curPlayState === "running" ||
curPlayState !== prevPlayStateRef.current)
(prevPendingRef.current !== pending ||
prevPlayStateRef.current !== curPlayState ||
curPlayState === "running")
)
onUpdateRef.current({
playState: animation.playState,
animate,
animation,
});
onUpdateRef.current({ playState: curPlayState, animate, animation });

prevPendingRef.current = pending;
prevPlayStateRef.current = curPlayState;
}

Expand Down

0 comments on commit 5060dbe

Please sign in to comment.