1
- import { ViewController } from '../components/nav/view-controller' ;
2
1
import { CSS , rafFrames , raf , transitionEnd } from '../util/dom' ;
3
- import { assign } from '../util/util' ;
2
+ import { assign , isDefined } from '../util/util' ;
4
3
5
4
6
5
/**
@@ -25,12 +24,14 @@ export class Animation {
25
24
private _fOnceFns : Array < Function > ;
26
25
private _wChg : boolean = false ;
27
26
private _rv : boolean ;
27
+ private _unregTrans : Function ;
28
+ private _tmr ;
28
29
29
30
public isPlaying : boolean ;
30
31
public hasTween : boolean ;
31
32
public meta ;
32
33
33
- constructor ( ele ?, opts = { } ) {
34
+ constructor ( ele ?, opts : AnimationOptions = { } ) {
34
35
this . _reset ( ) ;
35
36
this . element ( ele ) ;
36
37
@@ -54,6 +55,8 @@ export class Animation {
54
55
this . _fFns = [ ] ;
55
56
this . _fOnceFns = [ ] ;
56
57
58
+ this . _clearAsync ( ) ;
59
+
57
60
this . isPlaying = this . hasTween = this . _rv = false ;
58
61
this . _el = this . _easing = this . _dur = null ;
59
62
}
@@ -106,11 +109,11 @@ export class Animation {
106
109
return this ;
107
110
}
108
111
109
- from ( prop : string , val : string ) : Animation {
112
+ from ( prop : string , val ) : Animation {
110
113
return this . _addProp ( 'from' , prop , val ) ;
111
114
}
112
115
113
- to ( prop : string , val : string ) : Animation {
116
+ to ( prop : string , val ) : Animation {
114
117
return this . _addProp ( 'to' , prop , val ) ;
115
118
}
116
119
@@ -196,12 +199,12 @@ export class Animation {
196
199
}
197
200
}
198
201
199
- play ( ) {
202
+ play ( opts : PlayOptions = { } ) {
200
203
var self = this ;
204
+ var i ;
205
+ var duration = isDefined ( opts . duration ) ? opts . duration : self . _dur ;
201
206
202
- var i , fallbackTimerId , deregTransEnd ;
203
-
204
- console . debug ( 'Animation, play, duration' , self . _dur , 'easing' , self . _easing ) ;
207
+ console . debug ( 'Animation, play, duration' , duration , 'easing' , self . _easing ) ;
205
208
206
209
// always default that an animation does not tween
207
210
// a tween requires that an Animation class has an element
@@ -226,7 +229,10 @@ export class Animation {
226
229
// will recursively stage all child elements
227
230
self . _before ( ) ;
228
231
229
- if ( self . _dur > 30 ) {
232
+ // ensure all past transition end events have been cleared
233
+ this . _clearAsync ( ) ;
234
+
235
+ if ( duration > 30 ) {
230
236
// this animation has a duration, so it should animate
231
237
// place all the elements with their FROM properties
232
238
@@ -235,17 +241,17 @@ export class Animation {
235
241
236
242
self . _willChange ( true ) ;
237
243
238
- // set the TRANSITION END event
244
+ // set the async TRANSITION END event
239
245
// and run onFinishes when the transition ends
240
- self . _asyncEnd ( self . _dur ) ;
246
+ self . _asyncEnd ( duration ) ;
241
247
242
248
// begin each animation when everything is rendered in their place
243
249
// and the transition duration/easing is ready to go
244
250
rafFrames ( self . _opts . renderDelay / 16 , function ( ) {
245
251
// there's been a moment and the elements are in place
246
252
247
253
// now set the TRANSITION duration/easing
248
- self . _setTrans ( self . _dur , false ) ;
254
+ self . _setTrans ( duration , false ) ;
249
255
250
256
// wait a few moments again to wait for the transition
251
257
// info to take hold in the DOM
@@ -264,47 +270,73 @@ export class Animation {
264
270
// just go straight to the TO properties and call it done
265
271
self . _progress ( 1 ) ;
266
272
267
- // so there was no animation, immediately run the after
273
+ // since there was no animation, immediately run the after
268
274
self . _after ( ) ;
269
275
270
- // so there was no animation, it's done
276
+ // since there was no animation, it's done
271
277
// fire off all the onFinishes
272
278
self . _onFinish ( ) ;
273
279
}
274
280
}
275
281
276
- _asyncEnd ( duration : number ) {
282
+ stop ( opts : PlayOptions = { } ) {
277
283
var self = this ;
278
- var deregTransEnd , fallbackTimerId ;
284
+ var duration = isDefined ( opts . duration ) ? opts . duration : 0 ;
285
+ var stepValue = isDefined ( opts . stepValue ) ? opts . stepValue : 1 ;
279
286
280
- // set the TRANSITION END event
281
- deregTransEnd = transitionEnd ( self . _transEl ( ) , function ( ) {
282
- // transition has completed
283
- console . debug ( 'Animation, transition end' ) ;
287
+ // ensure all past transition end events have been cleared
288
+ this . _clearAsync ( ) ;
284
289
285
- // cancel the fallback timer so it doesn't fire also
286
- clearTimeout ( fallbackTimerId ) ;
290
+ // set the TO properties
291
+ self . _progress ( stepValue ) ;
287
292
288
- // set the after styles
293
+ if ( duration > 30 ) {
294
+ // this animation has a duration, so it should animate
295
+ // place all the elements with their TO properties
296
+
297
+ // now set the TRANSITION duration
298
+ self . _setTrans ( duration , true ) ;
299
+
300
+ // set the async TRANSITION END event
301
+ // and run onFinishes when the transition ends
302
+ self . _asyncEnd ( duration ) ;
303
+
304
+ } else {
305
+ // this animation does not have a duration, so it should not animate
306
+ // just go straight to the TO properties and call it done
289
307
self . _after ( ) ;
290
- self . _willChange ( false ) ;
308
+
309
+ // since there was no animation, it's done
310
+ // fire off all the onFinishes
291
311
self . _onFinish ( ) ;
292
- } ) ;
312
+ }
313
+ }
293
314
294
- // set a fallback timeout if the transition end event never fires
295
- fallbackTimerId = setTimeout ( function ( ) {
296
- // fallback timeout fired instead of the transition end
297
- console . debug ( 'Animation, fallback end' ) ;
315
+ _asyncEnd ( duration : number ) {
316
+ var self = this ;
298
317
299
- // deregister the transition end event listener
300
- deregTransEnd ( ) ;
318
+ function onTransitionEnd ( ev ) {
319
+ console . debug ( 'Animation async end,' , ( ev ? 'transitionEnd event' : 'fallback timeout' ) ) ;
320
+
321
+ // ensure transition end events and timeouts have been cleared
322
+ self . _clearAsync ( ) ;
301
323
302
324
// set the after styles
303
325
self . _after ( ) ;
304
326
self . _willChange ( false ) ;
305
327
self . _onFinish ( ) ;
328
+ }
329
+
330
+ // set the TRANSITION END event on one of the transition elements
331
+ self . _unregTrans = transitionEnd ( self . _transEl ( ) , onTransitionEnd ) ;
332
+
333
+ // set a fallback timeout if the transition end event never fires
334
+ self . _tmr = setTimeout ( onTransitionEnd , duration + 300 ) ;
335
+ }
306
336
307
- } , duration + 300 ) ;
337
+ _clearAsync ( ) {
338
+ this . _unregTrans && this . _unregTrans ( ) ;
339
+ clearTimeout ( this . _tmr ) ;
308
340
}
309
341
310
342
_progress ( stepValue : number ) {
@@ -565,7 +597,11 @@ export class Animation {
565
597
return this ;
566
598
}
567
599
568
- onFinish ( callback : Function , onceTimeCallback : boolean = false ) {
600
+ onFinish ( callback : Function , onceTimeCallback : boolean = false , clearOnFinishCallacks : boolean = false ) {
601
+ if ( clearOnFinishCallacks ) {
602
+ this . _fFns = [ ] ;
603
+ this . _fOnceFns = [ ] ;
604
+ }
569
605
if ( onceTimeCallback ) {
570
606
this . _fOnceFns . push ( callback ) ;
571
607
@@ -625,25 +661,15 @@ export class Animation {
625
661
/*
626
662
STATIC CLASSES
627
663
*/
628
- static create ( name : string ) : Animation {
664
+ static create ( name : string , opts : AnimationOptions = { } ) : Animation {
629
665
let AnimationClass = AnimationRegistry [ name ] ;
630
666
631
667
if ( ! AnimationClass ) {
632
668
// couldn't find an animation by the given name
633
669
// fallback to just the base Animation class
634
670
AnimationClass = Animation ;
635
671
}
636
- return new AnimationClass ( ) ;
637
- }
638
-
639
- static createTransition ( enteringView : ViewController , leavingView : ViewController , opts : any = { } ) : Animation {
640
- let TransitionClass = AnimationRegistry [ opts . animation ] ;
641
- if ( ! TransitionClass ) {
642
- // didn't find a transition animation, default to ios-transition
643
- TransitionClass = AnimationRegistry [ 'ios-transition' ] ;
644
- }
645
-
646
- return new TransitionClass ( enteringView , leavingView , opts ) ;
672
+ return new AnimationClass ( null , opts ) ;
647
673
}
648
674
649
675
static register ( name : string , AnimationClass ) {
@@ -652,6 +678,16 @@ export class Animation {
652
678
653
679
}
654
680
681
+ export interface AnimationOptions {
682
+ animation ?: string ;
683
+ renderDelay ?: number ;
684
+ }
685
+
686
+ export interface PlayOptions {
687
+ duration ?: number ;
688
+ stepValue ?: number ;
689
+ }
690
+
655
691
const doc : any = document ;
656
692
const TRANSFORMS = [
657
693
'translateX' , 'translateY' , 'translateZ' , 'scale' , 'scaleX' , 'scaleY' , 'scaleZ' ,
0 commit comments