| <!DOCTYPE html> |
| <title>The various animation longhands with progress based animations</title> |
| <link rel="help" src="https://drafts.csswg.org/css-animations-2"> |
| <link rel="help" src="https://github.com/w3c/csswg-drafts/issues/4862"> |
| <link rel="help" src="https://github.com/w3c/csswg-drafts/issues/6674"> |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| <script src="/web-animations/testcommon.js"></script> |
| <script src="support/testcommon.js"></script> |
| <style> |
| @keyframes anim { |
| from { translate: 0px; } |
| to { translate: 100px; } |
| } |
| #container { |
| width: 300px; |
| height: 300px; |
| overflow: scroll; |
| } |
| #target { |
| width: 100px; |
| height: 100px; |
| translate: none; |
| } |
| </style> |
| <body> |
| <div id="log"></div> |
| <script> |
| "use strict"; |
| |
| const createTargetAndScroller = function(t) { |
| let container = document.createElement('div'); |
| container.id = 'container'; |
| let target = document.createElement('div'); |
| target.id = 'target'; |
| let content = document.createElement('div'); |
| content.style.blockSize = '100%'; |
| |
| // The height of target is 100px and the content is 100%, so the scroll range |
| // is [0, 100]. |
| |
| // <div id='container'> |
| // <div id='target'></div> |
| // <div style='block-size: 100%;'></div> |
| // </div> |
| document.body.appendChild(container); |
| container.appendChild(target); |
| container.appendChild(content); |
| |
| if (t && typeof t.add_cleanup === 'function') { |
| t.add_cleanup(() => { |
| content.remove(); |
| target.remove(); |
| container.remove(); |
| }); |
| } |
| |
| return [target, container]; |
| }; |
| |
| async function scrollTop(element, value) { |
| element.scrollTop = value; |
| await waitForNextFrame(); |
| } |
| |
| // ------------------------------ |
| // Test animation-duration |
| // ------------------------------ |
| |
| promise_test(async t => { |
| let [target, scroller] = createTargetAndScroller(t); |
| target.style.animation = '10s linear anim scroll(nearest)'; |
| |
| await scrollTop(scroller, 25); // [0, 100]. |
| assert_equals(getComputedStyle(target).translate, '25px'); |
| }, 'animation-duration'); |
| |
| promise_test(async t => { |
| let [target, scroller] = createTargetAndScroller(t); |
| target.style.animation = '0s linear anim scroll(nearest)'; |
| |
| await scrollTop(scroller, 25); // [0, 100]. |
| assert_equals(getComputedStyle(target).translate, '100px'); |
| }, 'animation-duration: 0s'); |
| |
| |
| // ------------------------------ |
| // Test animation-iteration-count |
| // ------------------------------ |
| |
| promise_test(async t => { |
| let [target, scroller] = createTargetAndScroller(t); |
| target.style.animation = '10s linear anim scroll(nearest)'; |
| |
| await scrollTop(scroller, 25); // [0, 100]. |
| assert_equals(getComputedStyle(target).translate, '25px'); |
| |
| // Let animation become 50% in the 1st iteration. |
| target.style.animationIterationCount = '2'; |
| await waitForCSSScrollTimelineStyle(); |
| assert_equals(getComputedStyle(target).translate, '50px'); |
| |
| // Let animation become 0% in the 2nd iteration. |
| target.style.animationIterationCount = '4'; |
| await waitForCSSScrollTimelineStyle(); |
| assert_equals(getComputedStyle(target).translate, '0px'); |
| }, 'animation-iteration-count'); |
| |
| promise_test(async t => { |
| let [target, scroller] = createTargetAndScroller(t); |
| target.style.animation = '10s linear anim scroll(nearest)'; |
| target.style.animationIterationCount = '0'; |
| |
| await scrollTop(scroller, 25); // [0, 100]. |
| assert_equals(getComputedStyle(target).translate, '0px'); |
| }, 'animation-iteration-count: 0'); |
| |
| promise_test(async t => { |
| let [target, scroller] = createTargetAndScroller(t); |
| target.style.animation = '10s linear anim scroll(nearest)'; |
| target.style.animationIterationCount = 'infinite'; |
| |
| await scrollTop(scroller, 25); // [0, 100]. |
| assert_equals(getComputedStyle(target).translate, '100px'); |
| }, 'animation-iteration-count: infinite'); |
| |
| |
| // ------------------------------ |
| // Test animation-direction |
| // ------------------------------ |
| |
| promise_test(async t => { |
| let [target, scroller] = createTargetAndScroller(t); |
| target.style.animation = '10s linear anim scroll(nearest)'; |
| |
| await scrollTop(scroller, 25) // [0, 100]. |
| assert_equals(getComputedStyle(target).translate, '25px'); |
| }, 'animation-direction: normal'); |
| |
| promise_test(async t => { |
| let [target, scroller] = createTargetAndScroller(t); |
| target.style.animation = '10s linear anim scroll(nearest)'; |
| target.style.animationDirection = 'reverse'; |
| |
| await scrollTop(scroller, 25); // 25% in the reversing direction. |
| assert_equals(getComputedStyle(target).translate, '75px'); |
| }, 'animation-direction: reverse'); |
| |
| promise_test(async t => { |
| let [target, scroller] = createTargetAndScroller(t); |
| target.style.animation = '10s linear anim scroll(nearest)'; |
| target.style.animationIterationCount = '2'; |
| target.style.animationDirection = 'alternate'; |
| |
| await scrollTop(scroller, 10); // 20% in the 1st iteration. |
| assert_equals(getComputedStyle(target).translate, '20px'); |
| |
| await scrollTop(scroller, 60); // 20% in the 2nd iteration (reversing direction). |
| assert_equals(getComputedStyle(target).translate, '80px'); |
| }, 'animation-direction: alternate'); |
| |
| promise_test(async t => { |
| let [target, scroller] = createTargetAndScroller(t); |
| target.style.animation = '10s linear anim scroll(nearest)'; |
| target.style.animationIterationCount = '2'; |
| target.style.animationDirection = 'alternate-reverse'; |
| |
| await scrollTop(scroller, 10); // 20% in the 1st iteration (reversing direction). |
| assert_equals(getComputedStyle(target).translate, '80px'); |
| |
| await scrollTop(scroller, 60); // 20% in the 2nd iteration. |
| assert_equals(getComputedStyle(target).translate, '20px'); |
| }, 'animation-direction: alternate-reverse'); |
| |
| |
| // ------------------------------ |
| // Test animation-delay |
| // ------------------------------ |
| |
| promise_test(async t => { |
| let [target, scroller] = createTargetAndScroller(t); |
| target.style.animation = '10s linear anim scroll(nearest)'; |
| |
| await scrollTop(scroller, 25); // [0, 100]. |
| assert_equals(getComputedStyle(target).translate, '25px'); |
| |
| // (start delay: 10s) (duration: 10s) |
| // before active |
| // |--------------------|--------------------| |
| // 0px 50px 100px (The scroller) |
| // 0% 100% (The iteration progress) |
| |
| // Let animation be in before phase. |
| target.style.animationDelay = '10s'; |
| target.style.animationDelayStart = '10s'; // crbug.com/1375994 |
| assert_equals(getComputedStyle(target).translate, 'none'); |
| |
| await scrollTop(scroller, 50); // The animation enters active phase. |
| assert_equals(getComputedStyle(target).translate, '0px'); |
| |
| await scrollTop(scroller, 75); // The ieration progress is 50%. |
| assert_equals(getComputedStyle(target).translate, '50px'); |
| }, 'animation-delay with a positive value'); |
| |
| promise_test(async t => { |
| let [target, scroller] = createTargetAndScroller(t); |
| target.style.animation = '10s linear anim scroll(nearest)'; |
| |
| // active |
| // |--------------------| |
| // 0px 100px (The scroller) |
| // 50% 100% (The iteration progress) |
| |
| await scrollTop(scroller, 20); // [0, 100]. |
| target.style.animationDelay = '-5s'; |
| target.style.animationDelayStart = '-5s'; // crbug.com/1375994 |
| await waitForCSSScrollTimelineStyle(); |
| assert_equals(getComputedStyle(target).translate, '60px'); |
| }, 'animation-delay with a negative value'); |
| |
| |
| // ------------------------------ |
| // Test animation-fill-mode |
| // ------------------------------ |
| |
| promise_test(async t => { |
| let [target, scroller] = createTargetAndScroller(t); |
| target.style.animation = '10s linear anim scroll(nearest)'; |
| target.style.animationDelay = '10s'; |
| target.style.animationDelayStart = '10s'; // crbug.com/1375994 |
| |
| await scrollTop(scroller, 25); |
| assert_equals(getComputedStyle(target).translate, 'none'); |
| |
| target.style.animationFillMode = 'backwards'; |
| await waitForCSSScrollTimelineStyle(); |
| assert_equals(getComputedStyle(target).translate, '0px'); |
| }, 'animation-fill-mode'); |
| |
| </script> |
| </body> |