| <!DOCTYPE html> | |
| <meta charset=utf-8> | |
| <title>Test element-based scroll offset for scroll timeline.</title> | |
| <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: 500px; | |
| width: 500px; | |
| will-change: transform; | |
| } | |
| .contents { | |
| height: 2000px; | |
| width: 2000px; | |
| position: relative; | |
| } | |
| .vertical #start, .vertical #end { | |
| background: blue; | |
| border-top: 5px solid pink; | |
| box-sizing: border-box; | |
| width: 100%; | |
| height: 50px; | |
| } | |
| .vertical #start { | |
| position: absolute; | |
| top: 50px; | |
| } | |
| .vertical #end { | |
| position: absolute; | |
| top: 1050px; | |
| } | |
| .horizontal #start, .horizontal #end { | |
| background: blue; | |
| border-left:5px solid pink; | |
| box-sizing: border-box; | |
| height: 100%; | |
| width: 50px; | |
| } | |
| .horizontal #start { | |
| position: absolute; | |
| left: 50px; | |
| } | |
| .horizontal #end { | |
| position: absolute; | |
| left: 1050px; | |
| } | |
| </style> | |
| <div id="log"></div> | |
| <script> | |
| 'use strict'; | |
| async function createScrollAnimationTest(description, config) { | |
| promise_test(async t => { | |
| const scroller = createScrollerWithStartAndEnd(t, config.orientation); | |
| t.add_cleanup(() => scroller.remove()); | |
| const start = scroller.querySelector("#start"); | |
| const end = scroller.querySelector("#end"); | |
| // Force layout to ensure the scroll timeline gets the correct scroll | |
| // range. | |
| start.offsetHeight; | |
| const timeline = createScrollTimeline(t, { | |
| source: scroller, | |
| orientation: config.orientation, | |
| fill: 'both', | |
| scrollOffsets: | |
| [{target: start, ...config.start}, {target: end, ...config.end }] | |
| }); | |
| // Wait for new animation frame which allows the timeline to compute new | |
| // current time. | |
| await waitForNextFrame(); | |
| const animation = createScrollLinkedAnimation(t, timeline); | |
| const scrollRange = (config.orientation == 'vertical') | |
| ? end.offsetTop - start.offsetTop | |
| : end.offsetLeft - start.offsetLeft; | |
| // Verify initial start and current times in Idle state. | |
| assert_equals(animation.currentTime, null, | |
| "The current time is null in Idle state."); | |
| assert_equals(animation.startTime, null, | |
| "The start time is null in Idle state."); | |
| animation.play(); | |
| assert_true(animation.pending, "Animation is in pending state."); | |
| // Verify initial start and current times in Pending state. | |
| assert_percents_equal(animation.currentTime, 0, | |
| "The current time is zero in Pending state."); | |
| assert_percents_equal(animation.startTime, 0, | |
| "The start time is zero in Pending state."); | |
| await animation.ready; | |
| // Verify initial start and current times in Playing state. | |
| assert_percents_equal(animation.currentTime, 0, | |
| "The current time is zero in Playing state."); | |
| assert_percents_equal(animation.startTime, 0, | |
| "The start time is zero in Playing state."); | |
| // Now do some scrolling and make sure that the Animation current time is | |
| // correct. | |
| if (config.orientation == 'vertical') { | |
| scroller.scrollTo({top: config.scrollTo}); | |
| assert_equals(scroller.scrollTop, config.scrollTo); | |
| } else { | |
| scroller.scrollTo({left: config.scrollTo}); | |
| assert_equals(scroller.scrollLeft, config.scrollTo); | |
| } | |
| await waitForNextFrame(); | |
| assert_percents_approx_equal( | |
| animation.timeline.currentTime, | |
| config.expectedCurrentTime, | |
| scrollRange, | |
| "The timeline current time corresponds to the scroll position of " + | |
| "the scroller."); | |
| assert_percents_approx_equal( | |
| animation.currentTime, | |
| config.expectedCurrentTime, | |
| scrollRange, | |
| "The animation current time corresponds to the scroll position of " + | |
| "the scroller."); | |
| assert_percents_approx_equal( | |
| animation.effect.getComputedTiming().localTime, | |
| config.expectedCurrentTime, | |
| scrollRange, | |
| "Effect local time corresponds to the scroll position of the " + | |
| "scroller."); | |
| }, description); | |
| } | |
| // start is @ 50px | |
| // end is @ 1050px | |
| // both have 50px heights | |
| // scroller has 500px heights | |
| // For each test the expected start/end is in the comment to help with the | |
| // verification. | |
| // | |
| // Note: expectedCurrentTime values are percentages. They are used as such: | |
| // CSS.percent(expectedCurrentTime) | |
| const tests = { | |
| // offsets: [100, 1100] | |
| "at start": { | |
| scrollTo: 100, | |
| expectedCurrentTime: 0, | |
| }, | |
| // offsets: [100, 1100] | |
| "after start": { | |
| scrollTo: 200, | |
| expectedCurrentTime: 10, | |
| }, | |
| // offsets: [100, 1100] | |
| "at middle" : { | |
| scrollTo: 600, | |
| expectedCurrentTime: 50, | |
| }, | |
| // offsets: [100, 1100] | |
| "at end" : { | |
| scrollTo: 1099, | |
| expectedCurrentTime: 99.9, | |
| }, | |
| // offsets: [100, 1100] | |
| "after end" : { | |
| scrollTo: 1150, | |
| expectedCurrentTime: 100, | |
| }, | |
| // offsets: [75, 1075] | |
| "with threshold 0.5" : { | |
| // give threshold to both start and end to keep scrollRange | |
| // 1000 which simplifies the calculation. | |
| start: {threshold: 0.5}, | |
| end: {threshold: 0.5}, | |
| scrollTo: 600 - 25, | |
| expectedCurrentTime: 50, | |
| }, | |
| // offsets: [50, 1050] | |
| "with threshold 1.0": { | |
| start: {threshold: 1.0}, | |
| end: {threshold: 1.0}, | |
| scrollTo: 600 - 50, | |
| expectedCurrentTime: 50, | |
| }, | |
| // offset: [100, 550] | |
| "with end edge" : { | |
| end: {edge: "end"}, | |
| scrollTo: 325, | |
| expectedCurrentTime: 50, | |
| }, | |
| // offset: [100, 600] | |
| "with end edge and threshold 1.0": { | |
| end: { | |
| threshold: 1.0, | |
| edge: "end" | |
| }, | |
| scrollTo: 350, | |
| expectedCurrentTime: 50, | |
| }, | |
| }; | |
| for (let orientation of ['vertical', 'horizontal']) { | |
| for (let testName in tests) { | |
| const description = `Animation start and current times are correct given | |
| element-based offsets for orienation ${orientation} and ${testName}.`; | |
| const config = tests[testName]; | |
| config.orientation = orientation; | |
| createScrollAnimationTest(description, config); | |
| } | |
| } | |
| </script> |