1
- import { useRef , useLayoutEffect , useCallback , MutableRefObject } from "react" ;
1
+ import {
2
+ useRef ,
3
+ useLayoutEffect ,
4
+ useCallback ,
5
+ MutableRefObject ,
6
+ } from "react" ;
2
7
3
8
export type AnimationOptions = {
4
9
duration ?: number ;
@@ -22,17 +27,20 @@ export const useWebAnimation = ({
22
27
delay,
23
28
easing,
24
29
pause
25
- } : AnimationOptions ) : [ MutableRefObject < HTMLElement | undefined > , ( ) => void ] => {
30
+ } : AnimationOptions ) : [
31
+ MutableRefObject < HTMLElement | undefined > ,
32
+ ( ) => void
33
+ ] => {
26
34
const ref = useRef < HTMLElement > ( ) ;
27
35
const callback = useRef < any > ( ) ;
28
36
const animation = useRef < Animation | undefined > ( ) ;
29
37
const reverse = useRef ( false ) ;
30
38
31
39
const animate = useCallback (
32
40
( 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." ) ;
36
44
}
37
45
return ;
38
46
}
@@ -41,36 +49,44 @@ export const useWebAnimation = ({
41
49
ref . current ! . style [ property as any ] = getValue ( to ) ;
42
50
return ;
43
51
}
44
-
45
52
const timingObject : KeyframeAnimationOptions = {
46
53
duration : duration || 750 ,
47
54
iterations : 1 ,
48
55
delay,
49
- easing,
56
+ easing
50
57
} ;
51
58
52
59
callback . current = ( ) => {
53
60
if ( infinite ) {
54
- timingObject . direction = reverse . current ? "reverse" : "normal" ;
55
61
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 {
63
62
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
+
68
83
if ( animation . current && callback . current ) {
69
- animation . current ! . removeEventListener (
84
+ animation . current . removeEventListener (
70
85
"finish" ,
71
86
callback . current
72
87
) ;
73
88
}
89
+
74
90
animation . current = undefined ;
75
91
callback . current = undefined ;
76
92
} else {
@@ -89,16 +105,14 @@ export const useWebAnimation = ({
89
105
) ;
90
106
91
107
useLayoutEffect ( ( ) => {
92
- if ( ! pause ) {
93
- animate ( ) ;
94
- }
108
+ if ( ! pause ) animate ( ) ;
95
109
96
110
return ( ) => {
97
111
if ( animation . current && ! pause ) {
112
+ animation . current . cancel ( ) ;
98
113
if ( animation . current && callback . current ) {
99
- animation . current ! . removeEventListener ( "finish" , callback . current ) ;
114
+ animation . current . removeEventListener ( "finish" , callback . current ) ;
100
115
}
101
- animation . current . cancel ( ) ;
102
116
}
103
117
} ;
104
118
} , [ pause ] ) ;
0 commit comments