| <!DOCTYPE html> |
| <meta charset=utf-8> |
| <title>Animation.overallProgress</title> |
| <link rel="help" |
| href="https://drafts.csswg.org/web-animations-2/#the-overall-progress-of-an-animation"> |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| <script src="../../testcommon.js"></script> |
| <script src="../../../scroll-animations/scroll-timelines/testcommon.js"></script> |
| <body> |
| <style> |
| .scroller { |
| overflow-x: hidden; |
| overflow-y: auto; |
| height: 200px; |
| width: 100px; |
| will-change: transform; |
| } |
| .contents { |
| height: 1200px; |
| width: 100%; |
| } |
| #target { |
| height: 100px; |
| width: 100px; |
| background-color: green; |
| margin-top: -1000px; |
| } |
| </style> |
| <div id="log"></div> |
| <script> |
| 'use strict'; |
| |
| promise_test(async t => { |
| const animation = createScrollLinkedAnimation(t); |
| const scroller = animation.timeline.source; |
| const maxScroll = scroller.scrollHeight - scroller.clientHeight; |
| |
| assert_equals(animation.currentTime, null, |
| "The current time is null in Idle state."); |
| assert_equals(animation.overallProgress, null, |
| "The overallProgress is null since the currentTime is unresolved."); |
| |
| animation.play(); |
| assert_true(animation.pending, "Animation is in the pending state."); |
| assert_equals(animation.currentTime, null, |
| "The current time remains null while in the pending state."); |
| assert_equals(animation.overallProgress, null, |
| "The overallProgress is null since the currentTime is unresolved."); |
| |
| await animation.ready; |
| // Verify initial start and current times once ready. |
| assert_percents_equal(animation.currentTime, 0, |
| "The current time is resolved when ready."); |
| assert_equals(animation.overallProgress, 0, |
| "The overallProgress should be zero."); |
| |
| scroller.scrollTop = 0.4 * maxScroll; |
| |
| await waitForNextFrame(); |
| assert_percents_equal(animation.currentTime, 40, |
| "currentTime reflects overallProgress as a percentage"); |
| assert_approx_equals(animation.overallProgress, 0.4, 0.01, |
| "The overallProgress should match the scroll progress."); |
| }, "animation.overallProgress reflects the progress of a scroll animation as " + |
| "a number between 0 and 1"); |
| |
| promise_test(async t => { |
| const animation = createScrollLinkedAnimation(t); |
| const scroller = animation.timeline.source; |
| const maxScroll = scroller.scrollHeight - scroller.clientHeight; |
| |
| animation.play(); |
| await animation.ready; |
| // Verify initial start and current times once ready. |
| assert_percents_equal(animation.currentTime, 0, |
| "The current time is resolved when ready."); |
| assert_equals(animation.overallProgress, 0, |
| "The overallProgress should be zero."); |
| |
| scroller.scrollTop = 0.4 * maxScroll; |
| await waitForNextFrame(); |
| |
| let timing = animation.effect.getComputedTiming(); |
| // iteration duration should be 100%, overallProgress should reflect 40%. |
| assert_percents_equal(timing.duration, 100); |
| assert_percents_equal(animation.currentTime, 40, |
| "currentTime reflects progress as a percentage"); |
| assert_approx_equals(animation.overallProgress, 0.4, 0.01, |
| "The overallProgress should match the scroll progress."); |
| timing = animation.effect.getComputedTiming(); |
| |
| animation.effect.updateTiming({ iterations: 2 }); |
| |
| timing = animation.effect.getComputedTiming(); |
| // iteration duration should be 50%, overallProgress should still reflect 40% |
| // as it measures currentTime / effect endTime. |
| assert_percents_equal(timing.duration, 50); |
| assert_percents_equal(animation.currentTime, 40, |
| "currentTime reflects progress as a percentage"); |
| assert_approx_equals(animation.overallProgress, 0.4, 0.01, |
| "The overallProgress is should match the scroll progress."); |
| }, "animation.overallProgress reflects the overall progress of a scroll " + |
| "with multiple iterations."); |
| |
| promise_test(async t => { |
| const scroller = createScroller(t); |
| const view_timeline = createViewTimeline(t); |
| |
| const animation = createAnimation(t); |
| animation.rangeStart = { rangeName: 'contain', offset: CSS.percent(10) }; |
| animation.rangeEnd = { rangeName: 'contain', offset: CSS.percent(90) }; |
| animation.timeline = view_timeline; |
| |
| await animation.ready; |
| |
| // Cover range is [0, 300] |
| // Contain range is [100, 200] |
| // rangeStart offset of 10% => 110px |
| // rangeEnd offset of 90% => 190px |
| const target_pct = 40; |
| const target_scroll_top = 110 + (target_pct / 100) * (190 - 110); |
| scroller.scrollTop = target_scroll_top; |
| await waitForNextFrame(); |
| |
| const start_time = 110 / 300 * 100; |
| const timeline_time = target_scroll_top / 300 * 100; |
| const expected_current_time = timeline_time - start_time; |
| assert_percents_equal(animation.currentTime, expected_current_time, |
| "currentTime reflects progress as a percentage"); |
| assert_approx_equals(animation.overallProgress, target_pct / 100, 0.01, |
| "overallProgress should reflect fraction of view timeline range scroll " |
| + "through."); |
| }, "animation.overallProgress reflects the overall progress of a scroll " |
| + "that uses a view-timeline."); |
| |
| promise_test(async t => { |
| const scroller = createScroller(t); |
| const view_timeline = createViewTimeline(t); |
| |
| const animation = createAnimation(t); |
| animation.rangeStart = { rangeName: 'contain', offset: CSS.percent(10) }; |
| animation.rangeEnd = { rangeName: 'contain', offset: CSS.percent(90) }; |
| animation.timeline = view_timeline; |
| |
| await animation.ready; |
| |
| // Cover range is [0, 300] |
| // Contain range is [100, 200] |
| // rangeStart offset of 10% => 110px |
| // rangeEnd offset of 10% => 190px |
| |
| scroller.scrollTop = 100; |
| await waitForNextFrame(); |
| let timing = animation.effect.getComputedTiming(); |
| assert_less_than(animation.currentTime.value, 0, "currentTime is negative"); |
| assert_approx_equals(animation.overallProgress, 0, 0.01, "overallProgress " + |
| "is zero when scroll offset is less than range start."); |
| |
| scroller.scrollTop = 200; |
| await waitForNextFrame(); |
| assert_approx_equals(animation.currentTime.value, timing.endTime.value, 0.01, |
| "currentTime has reached endTime"); |
| assert_approx_equals(animation.overallProgress, 1, 0.01, "overallProgress " + |
| "is one when scroll offset goes past than range end."); |
| }, "overallProgress of a view-timeline is bounded between 0 and 1."); |
| |
| </script> |
| </body> |