reverse-animation.html (5331B)
1 <!DOCTYPE html> 2 <meta charset=utf-8> 3 <title>Reversing an animation</title> 4 <link rel="help" 5 href="https://drafts.csswg.org/web-animations/#reversing-an-animation-section"> 6 <script src="/resources/testharness.js"></script> 7 <script src="/resources/testharnessreport.js"></script> 8 <script src="/web-animations/testcommon.js"></script> 9 <script src="testcommon.js"></script> 10 <style> 11 .scroller { 12 overflow: auto; 13 height: 100px; 14 width: 100px; 15 will-change: transform; 16 } 17 18 .contents { 19 height: 1000px; 20 width: 100%; 21 } 22 </style> 23 <body> 24 <script> 25 'use strict'; 26 27 promise_test(async t => { 28 const animation = createScrollLinkedAnimation(t); 29 animation.reverse(); 30 animation.currentTime = CSSNumericValue.parse("40%"); 31 await animation.ready; 32 assert_percents_equal(animation.currentTime, 40); 33 }, 'Setting current time while reverse-pending preserves currentTime'); 34 35 promise_test(async t => { 36 const animation = createScrollLinkedAnimation(t); 37 animation.play(); 38 await animation.ready; 39 40 animation.currentTime = CSSNumericValue.parse("50%"); 41 const previousPlaybackRate = animation.playbackRate; 42 animation.reverse(); 43 assert_equals(animation.playbackRate, previousPlaybackRate, 44 'Playback rate should not have changed'); 45 await animation.ready; 46 47 assert_equals(animation.playbackRate, -previousPlaybackRate, 48 'Playback rate should be inverted'); 49 }, 'Reversing an animation inverts the playback rate'); 50 51 promise_test(async t => { 52 const animation = createScrollLinkedAnimation(t); 53 animation.play(); 54 animation.currentTime = CSSNumericValue.parse("40%"); 55 await animation.ready; 56 assert_percents_equal(animation.startTime, -40); 57 assert_percents_equal(animation.currentTime, 40); 58 59 animation.reverse(); 60 await animation.ready; 61 assert_percents_equal(animation.startTime, 100); 62 assert_percents_equal(animation.currentTime, 100); 63 }, 'Reversing an animation resets a sticky start time.'); 64 65 promise_test(async t => { 66 const animation = createScrollLinkedAnimation(t); 67 animation.play(); 68 assert_true(animation.pending, 69 'The animation is pending before we call reverse'); 70 71 animation.reverse(); 72 73 assert_true(animation.pending, 74 'The animation is still pending after calling reverse'); 75 }, 'Reversing an animation does not cause it to leave the pending state'); 76 77 promise_test(async t => { 78 const animation = createScrollLinkedAnimation(t); 79 animation.play(); 80 let readyResolved = false; 81 animation.ready.then(() => { readyResolved = true; }); 82 83 animation.reverse(); 84 85 await Promise.resolve(); 86 assert_false(readyResolved, 87 'ready promise should not have been resolved yet'); 88 }, 'Reversing an animation does not cause it to resolve the ready promise'); 89 90 promise_test(async t => { 91 const animation = createScrollLinkedAnimation(t); 92 animation.play(); 93 animation.playbackRate = -1; 94 animation.reverse(); 95 await animation.ready; 96 97 assert_percents_equal(animation.currentTime, 0); 98 }, 'Reversing an animation with a negative playback rate should cause ' + 99 'the animation to play in a forward direction'); 100 101 promise_test(async t => { 102 const animation = createScrollLinkedAnimation(t); 103 animation.play(); 104 animation.playbackRate = 0; 105 animation.currentTime = CSSNumericValue.parse("50%"); 106 animation.reverse(); 107 108 await animation.ready; 109 assert_equals(animation.playbackRate, 0, 110 'reverse() should preserve playbackRate if the playbackRate == 0'); 111 assert_percents_equal(animation.currentTime, 0, 112 'Anchors to range start boundary when playback rate is zero'); 113 }, 'Reversing when when playbackRate == 0 should preserve the playback rate'); 114 115 promise_test(async t => { 116 const animation = createScrollLinkedAnimation(t); 117 assert_equals(animation.currentTime, null); 118 119 animation.reverse(); 120 await animation.ready; 121 122 assert_percents_equal(animation.startTime, 100, 123 'animation.startTime should be at its effect end'); 124 assert_percents_equal(animation.currentTime, 100, 125 'animation.currentTime should be at its effect end'); 126 }, 'Reversing an idle animation aligns startTime with the rangeEnd boundary'); 127 128 promise_test(async t => { 129 const animation = createScrollLinkedAnimation(t); 130 const scroller = animation.timeline.source; 131 await runAndWaitForFrameUpdate(() => { 132 // Make the scroll timeline inactive. 133 scroller.style.overflow = 'visible'; 134 }); 135 136 assert_throws_dom('InvalidStateError', () => { animation.reverse(); }); 137 }, 'Reversing an animation without an active timeline throws an ' + 138 'InvalidStateError'); 139 140 promise_test(async t => { 141 const animation = createScrollLinkedAnimation(t); 142 animation.play(); 143 animation.currentTime = CSSNumericValue.parse("50%"); 144 animation.pause(); 145 await animation.ready; 146 147 animation.reverse(); 148 assert_equals(animation.playState, 'running', 149 'Animation.playState should be "running" after reverse()'); 150 }, 'Reversing an animation plays a pausing animation'); 151 152 promise_test(async t => { 153 const animation = createScrollLinkedAnimation(t); 154 animation.play(); 155 await animation.ready; 156 157 animation.updatePlaybackRate(2); 158 animation.reverse(); 159 160 await animation.ready; 161 assert_equals(animation.playbackRate, -2); 162 }, 'Reversing should use the negative pending playback rate'); 163 </script> 164 </body>