Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

<!DOCTYPE html>
<title>The various animation longhands with progress based animations</title>
<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";
setup(assert_implements_animation_timeline);
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);
await runAndWaitForFrameUpdate(() => {
target.style.animation = '10s linear anim';
target.style.animationTimeline = '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 forwards';
target.style.animationTimeline = '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);
await runAndWaitForFrameUpdate(() => {
target.style.animation = '10s linear anim';
target.style.animationTimeline = '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);
await runAndWaitForFrameUpdate(() => {
target.style.animation = '10s linear anim forwards';
target.style.animationTimeline = '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);
await runAndWaitForFrameUpdate(() => {
target.style.animation = '10s linear anim forwards';
target.style.animationTimeline = '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);
await runAndWaitForFrameUpdate(() => {
target.style.animation = '10s linear anim';
target.style.animationTimeline = '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);
await runAndWaitForFrameUpdate(() => {
target.style.animation = '10s linear anim';
target.style.animationTimeline = '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);
await runAndWaitForFrameUpdate(() => {
target.style.animation = '10s linear anim';
target.style.animationTimeline = '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);
await runAndWaitForFrameUpdate(() => {
target.style.animation = '10s linear anim';
target.style.animationTimeline = '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);
await runAndWaitForFrameUpdate(() => {
target.style.animation = '10s linear anim';
target.style.animationTimeline = '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);
await runAndWaitForFrameUpdate(() => {
target.style.animation = '10s linear anim';
target.style.animationTimeline = '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);
await runAndWaitForFrameUpdate(() => {
target.style.animation = '10s linear anim';
target.style.animationTimeline = '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>