Skip to content

Commit fd5b644

Browse files
authored
gracefully interrupt and reverse (#5)
1 parent 4e2349c commit fd5b644

File tree

1 file changed

+39
-25
lines changed

1 file changed

+39
-25
lines changed

src/index.ts

Lines changed: 39 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
import { useRef, useLayoutEffect, useCallback, MutableRefObject } from "react";
1+
import {
2+
useRef,
3+
useLayoutEffect,
4+
useCallback,
5+
MutableRefObject,
6+
} from "react";
27

38
export type AnimationOptions = {
49
duration?: number;
@@ -22,17 +27,20 @@ export const useWebAnimation = ({
2227
delay,
2328
easing,
2429
pause
25-
}: AnimationOptions): [MutableRefObject<HTMLElement | undefined>, () => void] => {
30+
}: AnimationOptions): [
31+
MutableRefObject<HTMLElement | undefined>,
32+
() => void
33+
] => {
2634
const ref = useRef<HTMLElement>();
2735
const callback = useRef<any>();
2836
const animation = useRef<Animation | undefined>();
2937
const reverse = useRef(false);
3038

3139
const animate = useCallback(
3240
(onComplete?: (() => void)) => {
33-
if (!ref.current || !ref.current.animate) {
34-
if (process.env.NODE_ENV !== 'production') {
35-
throw new Error('Please apply the ref to a dom-element.');
41+
if (!ref.current) {
42+
if (process.env.NODE_ENV !== "production") {
43+
throw new Error("Please apply the ref to a dom-element.");
3644
}
3745
return;
3846
}
@@ -41,36 +49,44 @@ export const useWebAnimation = ({
4149
ref.current!.style[property as any] = getValue(to);
4250
return;
4351
}
44-
4552
const timingObject: KeyframeAnimationOptions = {
4653
duration: duration || 750,
4754
iterations: 1,
4855
delay,
49-
easing,
56+
easing
5057
};
5158

5259
callback.current = () => {
5360
if (infinite) {
54-
timingObject.direction = reverse.current ? "reverse" : "normal";
5561
reverse.current = !reverse.current;
56-
57-
animation.current = ref.current!.animate(
58-
[{ [property]: getValue(from) }, { [property]: getValue(to) }],
59-
timingObject
60-
);
61-
animation.current.addEventListener("finish", callback.current);
62-
} else {
6362
if (animation.current) {
64-
ref.current!.style[property as any] = getValue(to);
65-
if (onComplete) {
66-
onComplete();
67-
}
63+
ref.current!.style[property as any] = getValue(reverse.current ? from : to);
64+
animation.current.reverse();
65+
} else {
66+
animation.current = ref.current!.animate(
67+
[{ [property]: getValue(from) }, { [property]: getValue(to) }],
68+
timingObject
69+
);
70+
animation.current.addEventListener("finish", callback.current);
71+
}
72+
} else {
73+
if (animation.current && animation.current.playState === "running") {
74+
reverse.current = !reverse.current;
75+
animation.current.reverse();
76+
animation.current.removeEventListener("finish", callback.current);
77+
animation.current.addEventListener("finish", callback.current);
78+
} else if (animation.current) {
79+
ref.current!.style[property as any] = getValue(reverse.current ? from : to);
80+
81+
if (onComplete) onComplete();
82+
6883
if (animation.current && callback.current) {
69-
animation.current!.removeEventListener(
84+
animation.current.removeEventListener(
7085
"finish",
7186
callback.current
7287
);
7388
}
89+
7490
animation.current = undefined;
7591
callback.current = undefined;
7692
} else {
@@ -89,16 +105,14 @@ export const useWebAnimation = ({
89105
);
90106

91107
useLayoutEffect(() => {
92-
if (!pause) {
93-
animate();
94-
}
108+
if (!pause) animate();
95109

96110
return () => {
97111
if (animation.current && !pause) {
112+
animation.current.cancel();
98113
if (animation.current && callback.current) {
99-
animation.current!.removeEventListener("finish", callback.current);
114+
animation.current.removeEventListener("finish", callback.current);
100115
}
101-
animation.current.cancel();
102116
}
103117
};
104118
}, [pause]);

0 commit comments

Comments
 (0)