| <!DOCTYPE html> |
| <meta charset=utf-8> |
| <title>Setting the current time of an animation</title> |
| <link rel="help" href="https://drafts.csswg.org/web-animations-1/#setting-the-current-time-of-an-animation"> |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| <script src="/web-animations/testcommon.js"></script> |
| <script src="testcommon.js"></script> |
| <style> |
| .scroller { |
| overflow: auto; |
| height: 200px; |
| width: 100px; |
| will-change: transform; |
| } |
| .contents { |
| height: 1000px; |
| width: 100%; |
| } |
| </style> |
| <body> |
| <div id="log"></div> |
| <script> |
| 'use strict'; |
| |
| promise_test(async t => { |
| const animation = createScrollLinkedAnimation(t); |
| const scroller = animation.timeline.scrollSource; |
| const maxScroll = scroller.scrollHeight - scroller.clientHeight; |
| scroller.scrollTop = 0.25 * maxScroll; |
| // Wait for new animation frame which allows the timeline to compute new |
| // current time. |
| await waitForNextFrame(); |
| animation.play(); |
| |
| await animation.ready; |
| |
| assert_throws_js(TypeError, () => { |
| animation.currentTime = null; |
| }); |
| }, 'Setting animation current time to null throws TypeError.'); |
| |
| promise_test(async t => { |
| const animation = createScrollLinkedAnimation(t); |
| assert_throws_dom('NotSupportedError', () => { |
| animation.currentTime = CSSNumericValue.parse("300"); |
| }); |
| assert_throws_dom('NotSupportedError', () => { |
| animation.currentTime = CSSNumericValue.parse("300ms"); |
| }); |
| assert_throws_dom('NotSupportedError', () => { |
| animation.currentTime = CSSNumericValue.parse("0.3s"); |
| }); |
| }, 'Setting the current time to an absolute time value throws exception'); |
| |
| promise_test(async t => { |
| const animation = createScrollLinkedAnimation(t); |
| const scroller = animation.timeline.scrollSource; |
| const maxScroll = scroller.scrollHeight - scroller.clientHeight; |
| scroller.scrollTop = 0.25 * maxScroll; |
| // Wait for new animation frame which allows the timeline to compute new |
| // current time. |
| await waitForNextFrame(); |
| |
| animation.currentTime = CSSNumericValue.parse("33.3%"); |
| |
| assert_percents_equal(animation.currentTime, 33.3, |
| "Animation current time should be equal to the set value." |
| ); |
| }, 'Set animation current time to a valid value without playing.'); |
| |
| promise_test(async t => { |
| const animation = createScrollLinkedAnimation(t); |
| const scroller = animation.timeline.scrollSource; |
| const maxScroll = scroller.scrollHeight - scroller.clientHeight; |
| scroller.scrollTop = 0.25 * maxScroll; |
| // Wait for new animation frame which allows the timeline to compute new |
| // current time. |
| await waitForNextFrame(); |
| animation.play(); |
| |
| await animation.ready; |
| animation.currentTime = CSSNumericValue.parse("33.3%"); |
| |
| assert_percents_equal(animation.currentTime, 33.3, |
| "Animation current time should be equal to the set value." |
| ); |
| }, 'Set animation current time to a valid value while playing.'); |
| |
| promise_test(async t => { |
| const animation = createScrollLinkedAnimation(t); |
| const scroller = animation.timeline.scrollSource; |
| const maxScroll = scroller.scrollHeight - scroller.clientHeight; |
| scroller.scrollTop = 0.25 * maxScroll; |
| // Wait for new animation frame which allows the timeline to compute new |
| // current time. |
| await waitForNextFrame(); |
| animation.play(); |
| |
| await animation.ready; |
| animation.currentTime = CSSNumericValue.parse("200%"); |
| |
| assert_equals(animation.playState, "finished"); |
| assert_percents_equal(animation.currentTime, 200, |
| "Animation current time should be equal to the set value." |
| ); |
| }, 'Set animation current time to a value beyond effect end.'); |
| |
| promise_test(async t => { |
| const animation = createScrollLinkedAnimation(t); |
| const scroller = animation.timeline.scrollSource; |
| const maxScroll = scroller.scrollHeight - scroller.clientHeight; |
| scroller.scrollTop = 0.25 * maxScroll; |
| // Wait for new animation frame which allows the timeline to compute new |
| // current time. |
| await waitForNextFrame(); |
| animation.play(); |
| |
| await animation.ready; |
| animation.currentTime = CSSNumericValue.parse("-10%"); |
| |
| assert_equals(animation.playState, "running"); |
| assert_percents_equal(animation.currentTime, -10, |
| "Animation current time should be equal to the set value." |
| ); |
| }, 'Set animation current time to a negative value.'); |
| |
| promise_test(async t => { |
| const animation = createScrollLinkedAnimation(t); |
| const scroller = animation.timeline.scrollSource; |
| const maxScroll = scroller.scrollHeight - scroller.clientHeight; |
| scroller.scrollTop = 0.25 * maxScroll; |
| // Wait for new animation frame which allows the timeline to compute new |
| // current time. |
| await waitForNextFrame(); |
| animation.play(); |
| |
| animation.currentTime = CSSNumericValue.parse("30%"); |
| |
| assert_equals(animation.playState, "running"); |
| assert_true(animation.pending); |
| assert_percents_equal(animation.currentTime, 30); |
| }, "Setting current time while play pending overrides the current time"); |
| |
| promise_test(async t => { |
| const animation = createScrollLinkedAnimation(t); |
| const scroller = animation.timeline.scrollSource; |
| const maxScroll = scroller.scrollHeight - scroller.clientHeight; |
| scroller.scrollTop = 0.25 * maxScroll; |
| // Wait for new animation frame which allows the timeline to compute new |
| // current time. |
| await waitForNextFrame(); |
| animation.play(); |
| |
| await animation.ready; |
| animation.currentTime = CSSNumericValue.parse("33.3%"); |
| |
| assert_percents_equal(animation.currentTime, 33.3, |
| "Animation current time should be equal to the set value." |
| ); |
| |
| // Cancel the animation and play it again, check that current time has reset |
| // to scroll offset based current time. |
| animation.cancel(); |
| animation.play(); |
| await animation.ready; |
| |
| assert_percents_equal(animation.currentTime, animation.timeline.currentTime, |
| "Animation current time should return to a value matching its" + |
| " timeline current time after animation is cancelled and played again." |
| ); |
| }, 'Setting animation.currentTime then restarting the animation should' + |
| ' reset the current time.'); |
| |
| promise_test(async t => { |
| const animation = createScrollLinkedAnimation(t); |
| const scroller = animation.timeline.scrollSource; |
| const maxScroll = scroller.scrollHeight - scroller.clientHeight; |
| scroller.scrollTop = 0.25 * maxScroll; |
| // Wait for new animation frame which allows the timeline to compute new |
| // current time. |
| await waitForNextFrame(); |
| animation.play(); |
| |
| await animation.ready; |
| const originalCurrentTime = animation.currentTime.value; |
| |
| // Set the current time to something other than where the scroll offset. |
| animation.currentTime = CSSNumericValue.parse("50%"); |
| |
| // Setting current time is internally setting the start time to |
| // scrollTimeline.currentTime - newAnimationCurrentTime. |
| // Which results in current time of (timeline.currentTime - start_time). |
| // This behavior puts the animation in a strange "out of sync" state between |
| // the scroller and the animation effect, this is currently expected |
| // behavior. |
| |
| const expectedStartTime = originalCurrentTime - animation.currentTime.value; |
| assert_percents_equal(animation.startTime, expectedStartTime, |
| "Animation current time should be updated when setting the current time" + |
| " to a time within the range of the animation."); |
| |
| scroller.scrollTop = 0.7 * maxScroll; |
| // Wait for new animation frame which allows the timeline to compute new |
| // current time. |
| await waitForNextFrame(); |
| |
| assert_percents_equal(animation.startTime, expectedStartTime, |
| "Animation start time should remain unchanged when the scroller changes" + |
| " position." |
| ); |
| assert_percents_equal(animation.currentTime, |
| animation.timeline.currentTime.value - animation.startTime.value, |
| "Animation current time should return to a value equal to" + |
| " (timeline.currentTime - animation.startTime) after timeline scroll" + |
| " source has been scrolled." |
| ); |
| }, 'Set Animation current time then scroll.'); |
| |
| promise_test(async t => { |
| const animation = createScrollLinkedAnimation(t); |
| const scroller = animation.timeline.scrollSource; |
| |
| // Wait for new animation frame which allows the timeline to compute new |
| // current time. |
| await waitForNextFrame(); |
| animation.play(); |
| await animation.ready; |
| |
| // Make the timeline inactive. |
| scroller.style.overflow = 'visible'; |
| scroller.scrollTop; |
| await waitForNextFrame(); |
| |
| assert_equals(animation.currentTime, null, |
| 'Current time is unresolved when the timeline is inactive.'); |
| |
| animation.currentTime = CSSNumericValue.parse("30%"); |
| assert_percents_equal(animation.currentTime, 30, |
| 'Animation current time should be equal to the set value.'); |
| assert_equals(animation.playState, 'paused', |
| 'Animation play state is \'paused\' when current time is set and ' + |
| 'timeline is inactive.'); |
| }, 'Animation current time and play state are correct when current time is ' + |
| 'set while the timeline is inactive.'); |
| |
| promise_test(async t => { |
| const animation = createScrollLinkedAnimation(t); |
| const scroller = animation.timeline.scrollSource; |
| |
| // Wait for new animation frame which allows the timeline to compute new |
| // current time. |
| await waitForNextFrame(); |
| animation.play(); |
| await animation.ready; |
| |
| // Make the timeline inactive. |
| scroller.style.overflow = 'visible'; |
| scroller.scrollTop; |
| await waitForNextFrame(); |
| |
| assert_equals(animation.timeline.currentTime, null, |
| 'Current time is unresolved when the timeline is inactive.'); |
| |
| animation.currentTime = CSSNumericValue.parse("30%"); |
| assert_percents_equal(animation.currentTime, 30, |
| 'Animation current time should be equal to the set value.'); |
| assert_equals(animation.playState, 'paused', |
| 'Animation play state is \'paused\' when current time is set and ' + |
| 'timeline is inactive.'); |
| |
| // Make the timeline active. |
| scroller.style.overflow = 'auto'; |
| scroller.scrollTop; |
| await waitForNextFrame(); |
| |
| assert_percents_equal(animation.timeline.currentTime, 0, |
| 'Current time is resolved when the timeline is active.'); |
| assert_percents_equal(animation.currentTime, 30, |
| 'Animation current time holds the set value.'); |
| assert_equals(animation.playState, 'paused', |
| 'Animation holds \'paused\' state.'); |
| }, 'Animation current time set while the timeline is inactive holds when the ' + |
| 'timeline becomes active again.'); |
| </script> |
| </body> |