effect-updateTiming.html (25561B)
1 <!doctype html> 2 <meta charset=utf-8> 3 <title>Scroll based animation: AnimationEffect.updateTiming</title> 4 <!-- Adapted to progressed based scroll animations from "wpt\web-animations\interfaces\AnimationEffect\updateTiming.html" --> 5 <link rel="help" href="https://drafts.csswg.org/web-animations-1/#dom-animationeffect-updatetiming"> 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 <script src="/web-animations/resources/easing-tests.js"></script> 11 <script src="/web-animations/resources/timing-tests.js"></script> 12 <style> 13 .scroller { 14 overflow: auto; 15 height: 100px; 16 width: 100px; 17 will-change: transform; 18 } 19 .contents { 20 height: 1000px; 21 width: 100%; 22 } 23 </style> 24 <body> 25 <div id="log"></div> 26 <script> 27 'use strict'; 28 29 // ------------------------------ 30 // delay 31 // ------------------------------ 32 33 promise_test(async t => { 34 const anim = createScrollLinkedAnimationWithTiming(t, {duration: 1000, delay: 200}) 35 anim.play(); 36 37 assert_equals(anim.effect.getTiming().delay, 200, 'initial delay 200'); 38 assert_equals(anim.effect.getComputedTiming().delay, 200, 39 'getComputedTiming() initially delay 200'); 40 41 anim.effect.updateTiming({ delay: 100 }); 42 assert_equals(anim.effect.getTiming().delay, 100, 'set delay 100'); 43 assert_equals(anim.effect.getComputedTiming().delay, 100, 44 'getComputedTiming() after set delay 100'); 45 }, 'Allows setting the delay to a positive number'); 46 47 test(t => { 48 const anim = createScrollLinkedAnimationWithTiming(t, {duration: 100, delay: -100}) 49 anim.play(); 50 anim.effect.updateTiming({ delay: -100 }); 51 assert_equals(anim.effect.getTiming().delay, -100, 'set delay -100'); 52 assert_equals(anim.effect.getComputedTiming().delay, -100, 53 'getComputedTiming() after set delay -100'); 54 assert_percents_equal(anim.effect.getComputedTiming().endTime, 0, 55 'getComputedTiming().endTime after set delay -100'); 56 }, 'Allows setting the delay to a negative number'); 57 58 promise_test(async t => { 59 const anim = createScrollLinkedAnimationWithTiming(t, {duration: 100}) 60 anim.play(); 61 await anim.ready; 62 anim.effect.updateTiming({ delay: 100 }); 63 assert_equals(anim.effect.getComputedTiming().progress, null); 64 assert_equals(anim.effect.getComputedTiming().currentIteration, null); 65 }, 'Allows setting the delay of an animation in progress: positive delay that' 66 + ' causes the animation to be no longer in-effect'); 67 68 promise_test(async t => { 69 const anim = 70 createScrollLinkedAnimationWithTiming(t, { fill: 'both', duration: 100 }); 71 anim.play(); 72 await anim.ready; 73 anim.effect.updateTiming({ delay: -50 }); 74 assert_equals(anim.effect.getComputedTiming().progress, 0.5); 75 }, 'Allows setting the delay of an animation in progress: negative delay that' 76 + ' seeks into the active interval'); 77 78 promise_test(async t => { 79 const anim = 80 createScrollLinkedAnimationWithTiming(t, { fill: 'both', duration: 100 }); 81 anim.play(); 82 await anim.ready; 83 anim.effect.updateTiming({ delay: -100 }); 84 assert_equals(anim.effect.getComputedTiming().progress, 1); 85 assert_equals(anim.effect.getComputedTiming().currentIteration, 0); 86 }, 'Allows setting the delay of an animation in progress: large negative delay' 87 + ' that causes the animation to be finished'); 88 89 for (const invalid of gBadDelayValues) { 90 test(t => { 91 const anim = createScrollLinkedAnimationWithTiming(t) 92 anim.play(); 93 assert_throws_js(TypeError, () => { 94 anim.effect.updateTiming({ delay: invalid }); 95 }); 96 }, `Throws when setting invalid delay value: ${invalid}`); 97 } 98 99 100 // ------------------------------ 101 // endDelay 102 // ------------------------------ 103 104 promise_test(async t => { 105 const anim = createScrollLinkedAnimationWithTiming(t, { duration: 2000 }); 106 anim.play(); 107 await anim.ready; 108 anim.effect.updateTiming({ endDelay: 123.45 }); 109 assert_time_equals_literal(anim.effect.getTiming().endDelay, 123.45, 110 'set endDelay 123.45'); 111 assert_time_equals_literal(anim.effect.getComputedTiming().endDelay, 123.45, 112 'getComputedTiming() after set endDelay 123.45'); 113 }, 'Allows setting the endDelay to a positive number'); 114 115 promise_test(async t => { 116 const anim = createScrollLinkedAnimationWithTiming(t, { duration: 2000 }); 117 anim.play(); 118 await anim.ready; 119 anim.effect.updateTiming({ endDelay: -1000 }); 120 assert_equals(anim.effect.getTiming().endDelay, -1000, 'set endDelay -1000'); 121 assert_equals(anim.effect.getComputedTiming().endDelay, -1000, 122 'getComputedTiming() after set endDelay -1000'); 123 }, 'Allows setting the endDelay to a negative number'); 124 125 promise_test(async t => { 126 const anim = createScrollLinkedAnimationWithTiming(t, { duration: 2000 }); 127 anim.play(); 128 await anim.ready; 129 assert_throws_js(TypeError, () => { 130 anim.effect.updateTiming({ endDelay: Infinity }); 131 }); 132 }, 'Throws when setting the endDelay to infinity'); 133 134 promise_test(async t => { 135 const anim = createScrollLinkedAnimationWithTiming(t, { duration: 2000 }); 136 anim.play(); 137 await anim.ready; 138 assert_throws_js(TypeError, () => { 139 anim.effect.updateTiming({ endDelay: -Infinity }); 140 }); 141 }, 'Throws when setting the endDelay to negative infinity'); 142 143 144 // ------------------------------ 145 // fill 146 // ------------------------------ 147 148 for (const fill of ['none', 'forwards', 'backwards', 'both']) { 149 test(t => { 150 const anim = createScrollLinkedAnimationWithTiming(t, { duration: 100 }) 151 anim.play(); 152 anim.effect.updateTiming({ fill }); 153 assert_equals(anim.effect.getTiming().fill, fill, 'set fill ' + fill); 154 assert_equals(anim.effect.getComputedTiming().fill, fill, 155 'getComputedTiming() after set fill ' + fill); 156 }, `Allows setting the fill to '${fill}'`); 157 } 158 159 160 // ------------------------------ 161 // iterationStart 162 // ------------------------------ 163 164 promise_test(async t => { 165 const anim = createScrollLinkedAnimationWithTiming(t, { iterationStart: 0.2, 166 iterations: 1, 167 fill: 'both', 168 duration: 100, 169 delay: 1 }) 170 anim.play(); 171 await anim.ready; 172 anim.effect.updateTiming({ iterationStart: 2.5 }); 173 assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.5); 174 assert_equals(anim.effect.getComputedTiming().currentIteration, 2); 175 }, 'Allows setting the iterationStart of an animation in progress:' 176 + ' backwards-filling'); 177 178 promise_test(async t => { 179 const anim = createScrollLinkedAnimationWithTiming(t, { iterationStart: 0.2, 180 iterations: 1, 181 fill: 'both', 182 duration: 100, 183 delay: 0 }) 184 anim.play(); 185 await anim.ready; 186 anim.effect.updateTiming({ iterationStart: 2.5 }); 187 assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.5); 188 assert_equals(anim.effect.getComputedTiming().currentIteration, 2); 189 }, 'Allows setting the iterationStart of an animation in progress:' 190 + ' active phase'); 191 192 promise_test(async t => { 193 const anim = createScrollLinkedAnimationWithTiming(t, { iterationStart: 0.3, 194 iterations: 1, 195 fill: 'both', 196 duration: 200, 197 delay: 0 }) 198 anim.play(); 199 await anim.ready; 200 assert_percents_equal(anim.currentTime, 0); 201 assert_percents_equal(anim.effect.getComputedTiming().localTime, 0, 202 "localTime"); 203 assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.3); 204 assert_equals(anim.effect.getComputedTiming().currentIteration, 0); 205 206 anim.finish(); 207 assert_percents_equal(anim.currentTime, 100); 208 assert_percents_equal(anim.effect.getComputedTiming().localTime, 100, 209 "localTime"); 210 assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.3); 211 assert_equals(anim.effect.getComputedTiming().currentIteration, 1); 212 213 anim.effect.updateTiming({ iterationStart: 2.5 }); 214 assert_percents_equal(anim.currentTime, 100); 215 assert_percents_equal(anim.effect.getComputedTiming().localTime, 100, 216 "localTime"); 217 assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.5); 218 assert_equals(anim.effect.getComputedTiming().currentIteration, 3); 219 }, 'Allows setting the iterationStart of an animation in progress:' 220 + ' forwards-filling'); 221 222 for (const invalid of gBadIterationStartValues) { 223 test(t => { 224 const anim = createScrollLinkedAnimationWithTiming(t) 225 anim.play(); 226 assert_throws_js(TypeError, () => { 227 anim.effect.updateTiming({ iterationStart: invalid }); 228 }, `setting ${invalid}`); 229 }, `Throws when setting invalid iterationStart value: ${invalid}`); 230 } 231 232 // ------------------------------ 233 // iterations 234 // ------------------------------ 235 236 test(t => { 237 const anim = createScrollLinkedAnimationWithTiming(t, { duration: 2000 }); 238 anim.play(); 239 anim.effect.updateTiming({ iterations: 2 }); 240 assert_equals(anim.effect.getTiming().iterations, 2, 'set duration 2'); 241 assert_equals(anim.effect.getComputedTiming().iterations, 2, 242 'getComputedTiming() after set iterations 2'); 243 }, 'Allows setting iterations to a double value'); 244 245 test(t => { 246 const anim = createScrollLinkedAnimationWithTiming(t, { duration: 2000 }); 247 anim.play(); 248 assert_throws_js(TypeError, () => { 249 anim.effect.updateTiming({ iterations: Infinity }); 250 }, "test"); 251 }, `Throws when setting iterations to Infinity`); 252 253 254 // progress based animations behave a bit differently than time based animations 255 // when changing iterations. 256 test(t => { 257 const anim = 258 createScrollLinkedAnimationWithTiming( 259 t, { duration: 100000, fill: 'both' }); 260 anim.play(); 261 anim.finish(); 262 263 assert_equals(anim.effect.getComputedTiming().progress, 1, 264 'progress when animation is finished'); 265 assert_percents_equal(anim.effect.getComputedTiming().duration, 100, 266 'duration when animation is finished'); 267 assert_equals(anim.effect.getComputedTiming().currentIteration, 0, 268 'current iteration when animation is finished'); 269 270 anim.effect.updateTiming({ iterations: 2 }); 271 272 assert_equals(anim.effect.getComputedTiming().progress, 1, 273 'progress after adding an iteration'); 274 assert_percents_equal(anim.effect.getComputedTiming().duration, 50, 275 'duration after adding an iteration'); 276 assert_equals(anim.effect.getComputedTiming().currentIteration, 1, 277 'current iteration after adding an iteration'); 278 279 anim.effect.updateTiming({ iterations: 4 }); 280 281 assert_equals(anim.effect.getComputedTiming().progress, 1, 282 'progress after setting iterations to 4'); 283 assert_percents_equal(anim.effect.getComputedTiming().duration, 25, 284 'duration after setting iterations to 4'); 285 assert_equals(anim.effect.getComputedTiming().currentIteration, 3, 286 'current iteration after setting iterations to 4'); 287 288 anim.effect.updateTiming({ iterations: 0 }); 289 290 assert_equals(anim.effect.getComputedTiming().progress, 0, 291 'progress after setting iterations to zero'); 292 assert_percents_equal(anim.effect.getComputedTiming().duration, 0, 293 'duration after setting iterations to zero'); 294 assert_equals(anim.effect.getComputedTiming().currentIteration, 0, 295 'current iteration after setting iterations to zero'); 296 }, 'Allows setting the iterations of an animation in progress'); 297 298 // Added test for checking duration "auto" 299 test(t => { 300 const anim = createScrollLinkedAnimationWithTiming(t, { fill: 'both' }); 301 anim.play(); 302 anim.finish(); 303 304 assert_equals(anim.effect.getComputedTiming().progress, 1, 305 'progress when animation is finished'); 306 assert_percents_equal(anim.effect.getComputedTiming().duration, 100, 307 'duration when animation is finished'); 308 assert_equals(anim.effect.getComputedTiming().currentIteration, 0, 309 'current iteration when animation is finished'); 310 311 anim.effect.updateTiming({ iterations: 2 }); 312 313 assert_equals(anim.effect.getComputedTiming().progress, 1, 314 'progress after adding an iteration'); 315 assert_percents_equal(anim.effect.getComputedTiming().duration, 50, 316 'duration after adding an iteration'); 317 assert_equals(anim.effect.getComputedTiming().currentIteration, 1, 318 'current iteration after adding an iteration'); 319 320 anim.effect.updateTiming({ iterations: 4 }); 321 322 assert_equals(anim.effect.getComputedTiming().progress, 1, 323 'progress after setting iterations to 4'); 324 assert_percents_equal(anim.effect.getComputedTiming().duration, 25, 325 'duration after setting iterations to 4'); 326 assert_equals(anim.effect.getComputedTiming().currentIteration, 3, 327 'current iteration after setting iterations to 4'); 328 329 anim.effect.updateTiming({ iterations: 0 }); 330 331 assert_equals(anim.effect.getComputedTiming().progress, 0, 332 'progress after setting iterations to zero'); 333 assert_percents_equal(anim.effect.getComputedTiming().duration, 0, 334 'duration after setting iterations to zero'); 335 assert_equals(anim.effect.getComputedTiming().currentIteration, 0, 336 'current iteration after setting iterations to zero'); 337 }, 'Allows setting the iterations of an animation in progress with duration ' + 338 '"auto"'); 339 340 341 // ------------------------------ 342 // duration 343 // ------------------------------ 344 test(t => { 345 const anim = createScrollLinkedAnimationWithTiming(t, { duration: Infinity }); 346 }, `Allows creating scroll linked animation with duration Infinity`); 347 348 // adapted for progress based animations 349 const gGoodDurationValuesForProgressBased = [ 350 // until duration returns a CSSNumberish which can handle percentages, 100% 351 // will be represented as 100 352 { specified: 123.45, computed: 100 }, 353 { specified: 'auto', computed: 100 }, 354 { specified: Infinity, computed: 100 }, 355 ]; 356 357 for (const duration of gGoodDurationValuesForProgressBased) { 358 test(t => { 359 const anim = createScrollLinkedAnimationWithTiming(t, 2000); 360 anim.play(); 361 anim.effect.updateTiming({ duration: duration.specified }); 362 if (typeof duration.specified === 'number') { 363 assert_time_equals_literal(anim.effect.getTiming().duration, 364 duration.specified, 365 'Updates specified duration'); 366 } else { 367 assert_equals(anim.effect.getTiming().duration, duration.specified, 368 'Updates specified duration'); 369 } 370 assert_percents_equal(anim.effect.getComputedTiming().duration, 371 duration.computed, 372 'Updates computed duration'); 373 }, `Allows setting the duration to ${duration.specified}`); 374 } 375 376 // adapted for progress based animations 377 const gBadDurationValuesForProgressBased = [ 378 -1, NaN, -Infinity, 'abc', '100' 379 ]; 380 381 for (const invalid of gBadDurationValuesForProgressBased) { 382 test(t => { 383 assert_throws_js(TypeError, () => { 384 const anim = createScrollLinkedAnimationWithTiming(t, { duration: invalid }) 385 anim.play(); 386 }); 387 }, 'Throws when setting invalid duration: ' 388 + (typeof invalid === 'string' ? `"${invalid}"` : invalid)); 389 } 390 391 test(t => { 392 const anim = 393 createScrollLinkedAnimationWithTiming( 394 t, { duration: 100000, fill: 'both' }); 395 anim.play(); 396 anim.finish(); 397 assert_equals(anim.effect.getComputedTiming().progress, 1, 398 'progress when animation is finished'); 399 anim.effect.updateTiming({ duration: anim.effect.getTiming().duration * 2 }); 400 assert_time_equals_literal(anim.effect.getComputedTiming().progress, 1, 401 'progress after doubling the duration'); 402 anim.effect.updateTiming({ duration: 0 }); 403 assert_equals(anim.effect.getComputedTiming().progress, 1, 404 'progress after setting duration to zero'); 405 anim.effect.updateTiming({ duration: 'auto' }); 406 assert_equals(anim.effect.getComputedTiming().progress, 1, 407 'progress after setting duration to \'auto\''); 408 }, 'Allows setting the duration of an animation in progress'); 409 410 promise_test(t => { 411 const anim = 412 createScrollLinkedAnimationWithTiming( 413 t, { duration: 100000, fill: 'both' }); 414 anim.play(); 415 return anim.ready.then(() => { 416 const originalStartTime = anim.startTime; 417 const originalCurrentTime = anim.currentTime; 418 assert_percents_equal( 419 anim.effect.getComputedTiming().duration, 420 100, 421 'Initial duration should be as set on KeyframeEffect' 422 ); 423 424 anim.effect.updateTiming({ duration: 200000 }); 425 assert_percents_equal( 426 anim.effect.getComputedTiming().duration, 427 100, 428 'Effect duration should remain at 100% for progress based animations' 429 ); 430 assert_percents_equal(anim.startTime, originalStartTime, 431 'startTime should be unaffected by changing effect ' + 432 'duration'); 433 434 assert_percents_equal(anim.currentTime, originalCurrentTime, 435 'currentTime should be unaffected by changing ' + 436 'effect duration'); 437 }); 438 }, 'Allows setting the duration of an animation in progress such that the' + 439 ' the start and current time do not change'); 440 441 442 // ------------------------------ 443 // direction 444 // ------------------------------ 445 446 test(t => { 447 const anim = createScrollLinkedAnimationWithTiming(t, { duration: 2000 }); 448 anim.play(); 449 450 const directions = ['normal', 'reverse', 'alternate', 'alternate-reverse']; 451 for (const direction of directions) { 452 anim.effect.updateTiming({ direction: direction }); 453 assert_equals(anim.effect.getTiming().direction, direction, 454 `set direction to ${direction}`); 455 } 456 }, 'Allows setting the direction to each of the possible keywords'); 457 458 promise_test(async t => { 459 const anim = 460 createScrollLinkedAnimationWithTiming( 461 t, { duration: 10000, direction: 'normal' }); 462 463 const scroller = anim.timeline.source; 464 const maxScroll = scroller.scrollHeight - scroller.clientHeight; 465 anim.play(); 466 await anim.ready; 467 scroller.scrollTop = maxScroll * 0.07 468 await waitForNextFrame(); 469 await waitForNextFrame(); 470 471 assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.07, 472 'progress before updating direction'); 473 474 anim.effect.updateTiming({ direction: 'reverse' }); 475 476 assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.93, 477 'progress after updating direction'); 478 }, 'Allows setting the direction of an animation in progress from \'normal\' ' + 479 'to \'reverse\''); 480 481 promise_test(async t => { 482 const anim = 483 createScrollLinkedAnimationWithTiming( 484 t, { duration: 10000, direction: 'normal' }); 485 anim.play(); 486 await anim.ready; 487 assert_equals(anim.effect.getComputedTiming().progress, 0, 488 'progress before updating direction'); 489 490 anim.effect.updateTiming({ direction: 'reverse' }); 491 492 assert_equals(anim.effect.getComputedTiming().progress, 1, 493 'progress after updating direction'); 494 }, 'Allows setting the direction of an animation in progress from \'normal\' to' 495 + ' \'reverse\' while at start of active interval'); 496 497 promise_test(async t => { 498 const anim = createScrollLinkedAnimationWithTiming(t, { fill: 'backwards', 499 duration: 10000, 500 delay: 10000, 501 direction: 'normal' }); 502 anim.play(); 503 await anim.ready; 504 assert_equals(anim.effect.getComputedTiming().progress, 0, 505 'progress before updating direction'); 506 507 anim.effect.updateTiming({ direction: 'reverse' }); 508 509 assert_equals(anim.effect.getComputedTiming().progress, 1, 510 'progress after updating direction'); 511 }, 'Allows setting the direction of an animation in progress from \'normal\' to' 512 + ' \'reverse\' while filling backwards'); 513 514 promise_test(async t => { 515 const anim = createScrollLinkedAnimationWithTiming(t, { iterations: 2, 516 duration: 10000, 517 direction: 'normal' }); 518 const scroller = anim.timeline.source; 519 const maxScroll = scroller.scrollHeight - scroller.clientHeight; 520 anim.play(); 521 await anim.ready; 522 scroller.scrollTop = maxScroll * 0.17 // 34% through first iteration 523 await waitForNextFrame(); 524 await waitForNextFrame(); 525 526 assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.34, 527 'progress before updating direction'); 528 529 anim.effect.updateTiming({ direction: 'alternate' }); 530 531 assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.34, 532 'progress after updating direction'); 533 }, 'Allows setting the direction of an animation in progress from \'normal\' to' 534 + ' \'alternate\''); 535 536 promise_test(async t => { 537 const anim = createScrollLinkedAnimationWithTiming(t, { iterations: 2, 538 duration: 10000, 539 direction: 'alternate' }); 540 const scroller = anim.timeline.source; 541 const maxScroll = scroller.scrollHeight - scroller.clientHeight; 542 anim.play(); 543 await anim.ready; 544 scroller.scrollTop = maxScroll * 0.17 545 await waitForNextFrame(); 546 await waitForNextFrame(); 547 // anim.currentTime = 17000; // 34% through first iteration 548 assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.34, 549 'progress before updating direction'); 550 551 anim.effect.updateTiming({ direction: 'alternate-reverse' }); 552 553 assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.66, 554 'progress after updating direction'); 555 }, 'Allows setting the direction of an animation in progress from \'alternate\'' 556 + ' to \'alternate-reverse\''); 557 558 559 // ------------------------------ 560 // easing 561 // ------------------------------ 562 563 async function assert_progress(animation, scrollPercent, easingFunction) { 564 const scroller = animation.timeline.source; 565 const maxScroll = scroller.scrollHeight - scroller.clientHeight; 566 scroller.scrollTop = maxScroll * scrollPercent 567 await waitForNextFrame(); 568 assert_approx_equals(animation.effect.getComputedTiming().progress, 569 easingFunction(scrollPercent), 570 0.01, 571 'The progress of the animation should be approximately' 572 + ` ${easingFunction(scrollPercent)} at ${scrollPercent}%`); 573 } 574 575 for (const options of gEasingTests) { 576 promise_test(async t => { 577 const anim = createScrollLinkedAnimationWithTiming(t, { duration: 100000, 578 fill: 'forwards' }); 579 anim.play(); 580 anim.effect.updateTiming({ easing: options.easing }); 581 assert_equals(anim.effect.getTiming().easing, 582 options.serialization || options.easing); 583 584 const easing = options.easingFunction; 585 await assert_progress(anim, 0, easing); 586 await assert_progress(anim, 0.25, easing); 587 await assert_progress(anim, 0.5, easing); 588 await assert_progress(anim, 0.75, easing); 589 await assert_progress(anim, 1, easing); 590 }, `Allows setting the easing to a ${options.desc}`); 591 } 592 593 for (const easing of gRoundtripEasings) { 594 test(t => { 595 const anim = createScrollLinkedAnimationWithTiming(t); 596 anim.play(); 597 anim.effect.updateTiming({ easing: easing }); 598 assert_equals(anim.effect.getTiming().easing, easing); 599 }, `Updates the specified value when setting the easing to '${easing}'`); 600 } 601 602 // Because of the delay being so large, this progress based animation is always 603 // in the finished state with progress 1. Included here because it is in the 604 // original test file for time based animations. 605 promise_test(async t => { 606 const delay = 1000000; 607 608 const anim = createScrollLinkedAnimationWithTiming(t, 609 { duration: 1000000, fill: 'both', delay: delay, easing: 'steps(2, start)' }); 610 611 const scroller = anim.timeline.source; 612 const maxScroll = scroller.scrollHeight - scroller.clientHeight; 613 anim.play(); 614 await anim.ready; 615 616 anim.effect.updateTiming({ easing: 'steps(2, end)' }); 617 assert_equals(anim.effect.getComputedTiming().progress, 0, 618 'easing replace to steps(2, end) at before phase'); 619 620 scroller.scrollTop = maxScroll * 0.875 621 await waitForNextFrame(); 622 await waitForNextFrame(); 623 624 assert_equals(anim.effect.getComputedTiming().progress, 0.5, 625 'change currentTime to active phase'); 626 627 anim.effect.updateTiming({ easing: 'steps(2, start)' }); 628 assert_equals(anim.effect.getComputedTiming().progress, 1, 629 'easing replace to steps(2, start) at active phase'); 630 631 scroller.scrollTop = maxScroll * 1.25 632 await waitForNextFrame(); 633 634 anim.effect.updateTiming({ easing: 'steps(2, end)' }); 635 assert_equals(anim.effect.getComputedTiming().progress, 1, 636 'easing replace to steps(2, end) again at after phase'); 637 }, 'Allows setting the easing of an animation in progress'); 638 </script> 639 </body>