1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
|
<!doctype html>
<meta charset=utf-8>
<title>Seamlessly updating the playback rate of an animation</title>
<link rel="help"
href="https://drafts.csswg.org/web-animations-1/#seamlessly-updating-the-playback-rate-of-an-animation">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
<body>
<div id="log"></div>
<script>
'use strict';
promise_test(async t => {
const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
await animation.ready;
animation.currentTime = 50 * MS_PER_SEC;
animation.updatePlaybackRate(0.5);
await animation.ready;
// Since the animation is in motion (and we want to test it while it is in
// motion!) we can't assert that the current time == 50s but we can check
// that the current time is NOT re-calculated by simply substituting in the
// new playback rate (i.e. without adjusting the start time). If that were
// the case the currentTime would jump to 25s. So we just test the currentTime
// hasn't gone backwards.
assert_greater_than_equal(animation.currentTime, 50 * MS_PER_SEC,
'Reducing the playback rate should not change the current time ' +
'of a playing animation');
animation.updatePlaybackRate(2);
await animation.ready;
// Likewise, we test here that the current time does not jump to 100s as it
// would if we naively applied a playbackRate of 2 without adjusting the
// startTime.
assert_less_than(animation.currentTime, 100 * MS_PER_SEC,
'Increasing the playback rate should not change the current time ' +
'of a playing animation');
}, 'Updating the playback rate maintains the current time');
promise_test(async t => {
const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
await animation.ready;
assert_false(animation.pending);
animation.updatePlaybackRate(2);
assert_true(animation.pending);
}, 'Updating the playback rate while running makes the animation pending');
promise_test(async t => {
const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
animation.currentTime = 50 * MS_PER_SEC;
assert_true(animation.pending);
animation.updatePlaybackRate(0.5);
// Check that the hold time is updated as expected
assert_time_equals_literal(animation.currentTime, 50 * MS_PER_SEC);
await animation.ready;
// As above, check that the currentTime is not calculated by simply
// substituting in the updated playbackRate without updating the startTime.
assert_greater_than_equal(animation.currentTime, 50 * MS_PER_SEC,
'Reducing the playback rate should not change the current time ' +
'of a play-pending animation');
}, 'Updating the playback rate on a play-pending animation maintains'
+ ' the current time');
promise_test(async t => {
const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
animation.currentTime = 50 * MS_PER_SEC;
await animation.ready;
animation.pause();
animation.updatePlaybackRate(0.5);
assert_greater_than_equal(animation.currentTime, 50 * MS_PER_SEC);
}, 'Updating the playback rate on a pause-pending animation maintains'
+ ' the current time');
promise_test(async t => {
const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
animation.updatePlaybackRate(2);
animation.updatePlaybackRate(3);
animation.updatePlaybackRate(4);
assert_equals(animation.playbackRate, 1);
await animation.ready;
assert_equals(animation.playbackRate, 4);
}, 'If a pending playback rate is set multiple times, the latest wins');
test(t => {
const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
animation.cancel();
animation.updatePlaybackRate(2);
assert_equals(animation.playbackRate, 2);
assert_false(animation.pending);
}, 'In the idle state, the playback rate is applied immediately');
promise_test(async t => {
const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
animation.pause();
await animation.ready;
animation.updatePlaybackRate(2);
assert_equals(animation.playbackRate, 2);
assert_false(animation.pending);
}, 'In the paused state, the playback rate is applied immediately');
promise_test(async t => {
const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
animation.finish();
assert_time_equals_literal(animation.currentTime, 100 * MS_PER_SEC);
assert_false(animation.pending);
animation.updatePlaybackRate(2);
assert_equals(animation.playbackRate, 2);
assert_time_equals_literal(animation.currentTime, 100 * MS_PER_SEC);
assert_false(animation.pending);
}, 'Updating the playback rate on a finished animation maintains'
+ ' the current time');
promise_test(async t => {
const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
animation.finish();
assert_time_equals_literal(animation.currentTime, 100 * MS_PER_SEC);
assert_false(animation.pending);
animation.updatePlaybackRate(0);
assert_equals(animation.playbackRate, 0);
assert_time_equals_literal(animation.currentTime, 100 * MS_PER_SEC);
assert_false(animation.pending);
}, 'Updating the playback rate to zero on a finished animation maintains'
+ ' the current time');
promise_test(async t => {
const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
await animation.ready;
// Get the animation in a state where it has an unresolved current time,
// a resolved start time (so it is not 'idle') and but no pending play task.
animation.timeline = null;
animation.startTime = 0;
assert_equals(animation.currentTime, null);
assert_equals(animation.playState, 'running');
// Make the effect end infinite.
animation.effect.updateTiming({ endDelay: 1e38 });
// Now we want to check that when we go to set a negative playback rate we
// don't end up throwing an InvalidStateError (which would happen if we ended
// up applying the auto-rewind behavior).
animation.updatePlaybackRate(-1);
// Furthermore, we should apply the playback rate immediately since the
// current time is unresolved.
assert_equals(animation.playbackRate, -1,
'We apply the pending playback rate immediately if the current time is ' +
'unresolved');
assert_false(animation.pending);
}, 'Updating the negative playback rate with the unresolved current time and'
+ ' a positive infinite associated effect end should not throw an'
+ ' exception');
</script>
</body>
|