@@ -14,7 +14,9 @@ describe('Plots.supplyAnimationDefaults', function() {
14
14
15
15
it ( 'supplies transition defaults' , function ( ) {
16
16
expect ( Plots . supplyAnimationDefaults ( { } ) ) . toEqual ( {
17
+ fromcurrent : false ,
17
18
mode : 'afterall' ,
19
+ direction : 'forward' ,
18
20
transition : {
19
21
duration : 500 ,
20
22
easing : 'cubic-in-out'
@@ -29,6 +31,8 @@ describe('Plots.supplyAnimationDefaults', function() {
29
31
it ( 'uses provided values' , function ( ) {
30
32
expect ( Plots . supplyAnimationDefaults ( {
31
33
mode : 'next' ,
34
+ fromcurrent : true ,
35
+ direction : 'reverse' ,
32
36
transition : {
33
37
duration : 600 ,
34
38
easing : 'elastic-in-out'
@@ -39,6 +43,8 @@ describe('Plots.supplyAnimationDefaults', function() {
39
43
}
40
44
} ) ) . toEqual ( {
41
45
mode : 'next' ,
46
+ fromcurrent : true ,
47
+ direction : 'reverse' ,
42
48
transition : {
43
49
duration : 600 ,
44
50
easing : 'elastic-in-out'
@@ -63,7 +69,12 @@ describe('Test animate API', function() {
63
69
function verifyFrameTransitionOrder ( gd , expectedFrames ) {
64
70
var calls = Plots . transition . calls ;
65
71
66
- expect ( calls . count ( ) ) . toEqual ( expectedFrames . length ) ;
72
+ var c1 = calls . count ( ) ;
73
+ var c2 = expectedFrames . length ;
74
+ expect ( c1 ) . toEqual ( c2 ) ;
75
+
76
+ // Prevent lots of ugly logging when it's already failed:
77
+ if ( c1 !== c2 ) return ;
67
78
68
79
for ( var i = 0 ; i < calls . count ( ) ; i ++ ) {
69
80
expect ( calls . argsFor ( i ) [ 1 ] ) . toEqual (
@@ -315,6 +326,104 @@ describe('Test animate API', function() {
315
326
} ) ;
316
327
}
317
328
329
+ describe ( 'Animation direction' , function ( ) {
330
+ var animOpts ;
331
+
332
+ beforeEach ( function ( ) {
333
+ animOpts = {
334
+ frame : { duration : 0 } ,
335
+ transition : { duration : 0 }
336
+ } ;
337
+ } ) ;
338
+
339
+ it ( 'animates frames by name in reverse' , function ( done ) {
340
+ animOpts . direction = 'reverse' ;
341
+
342
+ Plotly . animate ( gd , [ 'frame0' , 'frame2' , 'frame1' , 'frame3' ] , animOpts ) . then ( function ( ) {
343
+ verifyFrameTransitionOrder ( gd , [ 'frame3' , 'frame1' , 'frame2' , 'frame0' ] ) ;
344
+ verifyQueueEmpty ( gd ) ;
345
+ } ) . catch ( fail ) . then ( done ) ;
346
+ } ) ;
347
+
348
+ it ( 'animates a group in reverse' , function ( done ) {
349
+ animOpts . direction = 'reverse' ;
350
+ Plotly . animate ( gd , 'even-frames' , animOpts ) . then ( function ( ) {
351
+ verifyFrameTransitionOrder ( gd , [ 'frame2' , 'frame0' ] ) ;
352
+ verifyQueueEmpty ( gd ) ;
353
+ } ) . catch ( fail ) . then ( done ) ;
354
+ } ) ;
355
+ } ) ;
356
+
357
+ describe ( 'Animation fromcurrent' , function ( ) {
358
+ var animOpts ;
359
+
360
+ beforeEach ( function ( ) {
361
+ animOpts = {
362
+ frame : { duration : 0 } ,
363
+ transition : { duration : 0 } ,
364
+ fromcurrent : true
365
+ } ;
366
+ } ) ;
367
+
368
+ it ( 'animates starting at the current frame' , function ( done ) {
369
+ Plotly . animate ( gd , [ 'frame1' ] , animOpts ) . then ( function ( ) {
370
+ verifyFrameTransitionOrder ( gd , [ 'frame1' ] ) ;
371
+ verifyQueueEmpty ( gd ) ;
372
+
373
+ return Plotly . animate ( gd , null , animOpts ) ;
374
+ } ) . then ( function ( ) {
375
+ verifyFrameTransitionOrder ( gd , [ 'frame1' , 'frame2' , 'frame3' ] ) ;
376
+ verifyQueueEmpty ( gd ) ;
377
+ } ) . catch ( fail ) . then ( done ) ;
378
+ } ) ;
379
+
380
+ it ( 'plays from the start when current frame = last frame' , function ( done ) {
381
+ Plotly . animate ( gd , null , animOpts ) . then ( function ( ) {
382
+ verifyFrameTransitionOrder ( gd , [ 'base' , 'frame0' , 'frame1' , 'frame2' , 'frame3' ] ) ;
383
+ verifyQueueEmpty ( gd ) ;
384
+
385
+ return Plotly . animate ( gd , null , animOpts ) ;
386
+ } ) . then ( function ( ) {
387
+ verifyFrameTransitionOrder ( gd , [
388
+ 'base' , 'frame0' , 'frame1' , 'frame2' , 'frame3' ,
389
+ 'base' , 'frame0' , 'frame1' , 'frame2' , 'frame3'
390
+ ] ) ;
391
+
392
+ verifyQueueEmpty ( gd ) ;
393
+ } ) . catch ( fail ) . then ( done ) ;
394
+ } ) ;
395
+
396
+ it ( 'animates in reverse starting at the current frame' , function ( done ) {
397
+ animOpts . direction = 'reverse' ;
398
+
399
+ Plotly . animate ( gd , [ 'frame1' ] , animOpts ) . then ( function ( ) {
400
+ verifyFrameTransitionOrder ( gd , [ 'frame1' ] ) ;
401
+ verifyQueueEmpty ( gd ) ;
402
+ return Plotly . animate ( gd , null , animOpts ) ;
403
+ } ) . then ( function ( ) {
404
+ verifyFrameTransitionOrder ( gd , [ 'frame1' , 'frame0' , 'base' ] ) ;
405
+ verifyQueueEmpty ( gd ) ;
406
+ } ) . catch ( fail ) . then ( done ) ;
407
+ } ) ;
408
+
409
+ it ( 'plays in reverse from the end when current frame = first frame' , function ( done ) {
410
+ animOpts . direction = 'reverse' ;
411
+
412
+ Plotly . animate ( gd , [ 'base' ] , animOpts ) . then ( function ( ) {
413
+ verifyFrameTransitionOrder ( gd , [ 'base' ] ) ;
414
+ verifyQueueEmpty ( gd ) ;
415
+
416
+ return Plotly . animate ( gd , null , animOpts ) ;
417
+ } ) . then ( function ( ) {
418
+ verifyFrameTransitionOrder ( gd , [
419
+ 'base' , 'frame3' , 'frame2' , 'frame1' , 'frame0' , 'base'
420
+ ] ) ;
421
+
422
+ verifyQueueEmpty ( gd ) ;
423
+ } ) . catch ( fail ) . then ( done ) ;
424
+ } ) ;
425
+ } ) ;
426
+
318
427
// The tests above use promises to ensure ordering, but the tests below this call Plotly.animate
319
428
// without chaining promises which would result in race conditions. This is not invalid behavior,
320
429
// but it doesn't ensure proper ordering and completion, so these must be performed with finite
0 commit comments