@@ -9,86 +9,88 @@ interface CallbackStore {
99 [ frameId : string ] : ( ) => void ;
1010}
1111
12- export const statefulAnimationGenerator = < K extends CallbackKeyframe , T > (
13- generator : ( keyframe : K ) => Point [ ] ,
14- renderer : ( points : Point [ ] ) => T ,
15- checker : ( keyframe : K , index : number ) => void ,
16- ) => ( ) => {
17- let internalFrames : InternalKeyframe [ ] = [ ] ;
18- let renderCache : RenderCache = { } ;
19- let callbackStore : CallbackStore = { } ;
20-
21- // Keep track of paused state.
22- let pausedAt = 0 ;
23- let pauseOffset = 0 ;
24- const getAnimationTimestamp = ( ) => Date . now ( ) - pauseOffset ;
25- const isPaused = ( ) => pausedAt !== 0 ;
26-
27- const play = ( ) => {
28- if ( ! isPaused ( ) ) return ;
29- pauseOffset += getAnimationTimestamp ( ) - pausedAt ;
30- pausedAt = 0 ;
12+ export const statefulAnimationGenerator =
13+ < K extends CallbackKeyframe , T > (
14+ generator : ( keyframe : K ) => Point [ ] ,
15+ renderer : ( points : Point [ ] ) => T ,
16+ checker : ( keyframe : K , index : number ) => void ,
17+ ) =>
18+ ( ) => {
19+ let internalFrames : InternalKeyframe [ ] = [ ] ;
20+ let renderCache : RenderCache = { } ;
21+ let callbackStore : CallbackStore = { } ;
22+
23+ // Keep track of paused state.
24+ let pausedAt = 0 ;
25+ let pauseOffset = 0 ;
26+ const getAnimationTimestamp = ( ) => Date . now ( ) - pauseOffset ;
27+ const isPaused = ( ) => pausedAt !== 0 ;
28+
29+ const play = ( ) => {
30+ if ( ! isPaused ( ) ) return ;
31+ pauseOffset += getAnimationTimestamp ( ) - pausedAt ;
32+ pausedAt = 0 ;
33+ } ;
34+
35+ const pause = ( ) => {
36+ if ( isPaused ( ) ) return ;
37+ pausedAt = getAnimationTimestamp ( ) ;
38+ } ;
39+
40+ const playPause = ( ) => {
41+ `` ;
42+ if ( isPaused ( ) ) {
43+ play ( ) ;
44+ } else {
45+ pause ( ) ;
46+ }
47+ } ;
48+
49+ const renderFrame = ( ) : T => {
50+ const renderOutput = renderFramesAt ( {
51+ renderCache : renderCache ,
52+ timestamp : isPaused ( ) ? pausedAt : getAnimationTimestamp ( ) ,
53+ currentFrames : internalFrames ,
54+ } ) ;
55+
56+ // Update render cache with returned value.
57+ renderCache = renderOutput . renderCache ;
58+
59+ // Invoke callback if defined and the first time the frame is reached.
60+ if ( renderOutput . lastFrameId && callbackStore [ renderOutput . lastFrameId ] ) {
61+ callbackStore [ renderOutput . lastFrameId ] ( ) ;
62+ delete callbackStore [ renderOutput . lastFrameId ] ;
63+ }
64+
65+ return renderer ( renderOutput . points ) ;
66+ } ;
67+
68+ const transition = ( ...keyframes : K [ ] ) => {
69+ // Make sure frame info is valid.
70+ for ( let i = 0 ; i < keyframes . length ; i ++ ) {
71+ checker ( keyframes [ i ] , i ) ;
72+ }
73+
74+ const transitionOutput = transitionFrames < K > ( {
75+ renderCache : renderCache ,
76+ timestamp : getAnimationTimestamp ( ) ,
77+ currentFrames : internalFrames ,
78+ newFrames : keyframes ,
79+ shapeGenerator : generator ,
80+ } ) ;
81+
82+ // Reset internal state..
83+ internalFrames = transitionOutput . newFrames ;
84+ callbackStore = { } ;
85+ renderCache = { } ;
86+
87+ // Populate callback store using returned frame ids.
88+ for ( const newFrame of internalFrames ) {
89+ if ( newFrame . isSynthetic ) continue ;
90+ const { callback} = keyframes [ newFrame . transitionSourceFrameIndex ] ;
91+ if ( callback ) callbackStore [ newFrame . id ] = callback ;
92+ }
93+ } ;
94+
95+ return { renderFrame, transition, play, pause, playPause} ;
3196 } ;
32-
33- const pause = ( ) => {
34- if ( isPaused ( ) ) return ;
35- pausedAt = getAnimationTimestamp ( ) ;
36- } ;
37-
38- const playPause = ( ) => {
39- `` ;
40- if ( isPaused ( ) ) {
41- play ( ) ;
42- } else {
43- pause ( ) ;
44- }
45- } ;
46-
47- const renderFrame = ( ) : T => {
48- const renderOutput = renderFramesAt ( {
49- renderCache : renderCache ,
50- timestamp : isPaused ( ) ? pausedAt : getAnimationTimestamp ( ) ,
51- currentFrames : internalFrames ,
52- } ) ;
53-
54- // Update render cache with returned value.
55- renderCache = renderOutput . renderCache ;
56-
57- // Invoke callback if defined and the first time the frame is reached.
58- if ( renderOutput . lastFrameId && callbackStore [ renderOutput . lastFrameId ] ) {
59- callbackStore [ renderOutput . lastFrameId ] ( ) ;
60- delete callbackStore [ renderOutput . lastFrameId ] ;
61- }
62-
63- return renderer ( renderOutput . points ) ;
64- } ;
65-
66- const transition = ( ...keyframes : K [ ] ) => {
67- // Make sure frame info is valid.
68- for ( let i = 0 ; i < keyframes . length ; i ++ ) {
69- checker ( keyframes [ i ] , i ) ;
70- }
71-
72- const transitionOutput = transitionFrames < K > ( {
73- renderCache : renderCache ,
74- timestamp : getAnimationTimestamp ( ) ,
75- currentFrames : internalFrames ,
76- newFrames : keyframes ,
77- shapeGenerator : generator ,
78- } ) ;
79-
80- // Reset internal state..
81- internalFrames = transitionOutput . newFrames ;
82- callbackStore = { } ;
83- renderCache = { } ;
84-
85- // Populate callback store using returned frame ids.
86- for ( const newFrame of internalFrames ) {
87- if ( newFrame . isSynthetic ) continue ;
88- const { callback} = keyframes [ newFrame . transitionSourceFrameIndex ] ;
89- if ( callback ) callbackStore [ newFrame . id ] = callback ;
90- }
91- } ;
92-
93- return { renderFrame, transition, play, pause, playPause} ;
94- } ;
0 commit comments