239 lines
6 KiB
HTML
239 lines
6 KiB
HTML
<!DOCTYPE html>
|
|
<title>View timelines and animation attachment ranges</title>
|
|
<link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#named-timeline-range">
|
|
<link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#animation-range">
|
|
<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 { z-index: 0; background-color: skyblue;}
|
|
to { z-index: 100; background-color: coral; }
|
|
}
|
|
#scroller {
|
|
border: 10px solid lightgray;
|
|
overflow-y: scroll;
|
|
width: 200px;
|
|
height: 200px;
|
|
}
|
|
#scroller > div {
|
|
margin: 800px 0px;
|
|
width: 100px;
|
|
height: 100px;
|
|
}
|
|
#target {
|
|
font-size: 10px;
|
|
background-color: green;
|
|
z-index: -1;
|
|
}
|
|
</style>
|
|
<main id=main>
|
|
</main>
|
|
|
|
<template id=template_without_scope>
|
|
<div id=scroller>
|
|
<div id=target class=timeline></div>
|
|
</div>
|
|
</template>
|
|
|
|
<template id=template_with_scope>
|
|
<div id=scope>
|
|
<div id=target></div>
|
|
<div id=scroller>
|
|
<div class=timeline></div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
setup(assert_implements_animation_timeline);
|
|
|
|
function inflate(t, template) {
|
|
t.add_cleanup(() => main.replaceChildren());
|
|
main.append(template.content.cloneNode(true));
|
|
}
|
|
async function scrollTop(e, value) {
|
|
e.scrollTop = value;
|
|
await waitForNextFrame();
|
|
}
|
|
async function waitForAnimationReady(target) {
|
|
await waitForNextFrame();
|
|
await Promise.all(target.getAnimations().map(x => x.ready));
|
|
}
|
|
async function assertValueAt(scroller, target, args) {
|
|
await waitForAnimationReady(target);
|
|
await scrollTop(scroller, args.scrollTop);
|
|
assert_equals(getComputedStyle(target).zIndex, args.expected.toString());
|
|
}
|
|
function test_animation_range(options, template, desc_suffix) {
|
|
if (template === undefined)
|
|
template = template_without_scope;
|
|
if (desc_suffix === undefined)
|
|
desc_suffix = '';
|
|
|
|
promise_test(async (t) => {
|
|
inflate(t, template);
|
|
let scroller = main.querySelector('#scroller');
|
|
let target = main.querySelector('#target');
|
|
let timeline = main.querySelector('.timeline');
|
|
let scope = main.querySelector('#scope');
|
|
|
|
if (scope != null) {
|
|
scope.style.timelineScope = '--t1';
|
|
}
|
|
|
|
timeline.style.viewTimeline = '--t1';
|
|
target.style.animation = 'anim auto linear';
|
|
target.style.animationTimeline = '--t1';
|
|
target.style.animationRangeStart = options.rangeStart;
|
|
target.style.animationRangeEnd = options.rangeEnd;
|
|
|
|
// Accommodates floating point precision errors at the endpoints.
|
|
target.style.animationFillMode = 'both';
|
|
|
|
// 0%
|
|
await assertValueAt(scroller, target,
|
|
{ scrollTop: options.startOffset, expected: 0 });
|
|
// 50%
|
|
await assertValueAt(scroller, target,
|
|
{ scrollTop: (options.startOffset + options.endOffset) / 2, expected: 50 });
|
|
// 100%
|
|
await assertValueAt(scroller, target,
|
|
{ scrollTop: options.endOffset, expected: 100 });
|
|
|
|
// Test before/after phases (need to clear the fill mode for that).
|
|
target.style.animationFillMode = 'initial';
|
|
await assertValueAt(scroller, target,
|
|
{ scrollTop: options.startOffset - 10, expected: -1 });
|
|
await assertValueAt(scroller, target,
|
|
{ scrollTop: options.endOffset + 10, expected: -1 });
|
|
// Check 50% again without fill mode.
|
|
await assertValueAt(scroller, target,
|
|
{ scrollTop: (options.startOffset + options.endOffset) / 2, expected: 50 });
|
|
|
|
}, `Animation with ranges [${options.rangeStart}, ${options.rangeEnd}] ${desc_suffix}`.trim());
|
|
}
|
|
|
|
test_animation_range({
|
|
rangeStart: 'initial',
|
|
rangeEnd: 'initial',
|
|
startOffset: 600,
|
|
endOffset: 900
|
|
});
|
|
|
|
test_animation_range({
|
|
rangeStart: 'cover 0%',
|
|
rangeEnd: 'cover 100%',
|
|
startOffset: 600,
|
|
endOffset: 900
|
|
});
|
|
|
|
test_animation_range({
|
|
rangeStart: 'contain 0%',
|
|
rangeEnd: 'contain 100%',
|
|
startOffset: 700,
|
|
endOffset: 800
|
|
});
|
|
|
|
|
|
test_animation_range({
|
|
rangeStart: 'entry 0%',
|
|
rangeEnd: 'entry 100%',
|
|
startOffset: 600,
|
|
endOffset: 700
|
|
});
|
|
|
|
test_animation_range({
|
|
rangeStart: 'exit 0%',
|
|
rangeEnd: 'exit 100%',
|
|
startOffset: 800,
|
|
endOffset: 900
|
|
});
|
|
|
|
test_animation_range({
|
|
rangeStart: 'contain -50%',
|
|
rangeEnd: 'entry 200%',
|
|
startOffset: 650,
|
|
endOffset: 800
|
|
});
|
|
|
|
test_animation_range({
|
|
rangeStart: 'entry 0%',
|
|
rangeEnd: 'exit 100%',
|
|
startOffset: 600,
|
|
endOffset: 900
|
|
});
|
|
|
|
test_animation_range({
|
|
rangeStart: 'cover 20px',
|
|
rangeEnd: 'cover 100px',
|
|
startOffset: 620,
|
|
endOffset: 700
|
|
});
|
|
|
|
test_animation_range({
|
|
rangeStart: 'contain 20px',
|
|
rangeEnd: 'contain 100px',
|
|
startOffset: 720,
|
|
endOffset: 800
|
|
});
|
|
|
|
test_animation_range({
|
|
rangeStart: 'entry 20px',
|
|
rangeEnd: 'entry 100px',
|
|
startOffset: 620,
|
|
endOffset: 700
|
|
});
|
|
|
|
test_animation_range({
|
|
rangeStart: 'entry-crossing 20px',
|
|
rangeEnd: 'entry-crossing 100px',
|
|
startOffset: 620,
|
|
endOffset: 700
|
|
});
|
|
|
|
test_animation_range({
|
|
rangeStart: 'exit 20px',
|
|
rangeEnd: 'exit 80px',
|
|
startOffset: 820,
|
|
endOffset: 880
|
|
});
|
|
|
|
test_animation_range({
|
|
rangeStart: 'exit-crossing 20px',
|
|
rangeEnd: 'exit-crossing 80px',
|
|
startOffset: 820,
|
|
endOffset: 880
|
|
});
|
|
|
|
test_animation_range({
|
|
rangeStart: 'contain 20px',
|
|
rangeEnd: 'contain calc(100px - 10%)',
|
|
startOffset: 720,
|
|
endOffset: 790
|
|
});
|
|
|
|
test_animation_range({
|
|
rangeStart: 'exit 2em',
|
|
rangeEnd: 'exit 8em',
|
|
startOffset: 820,
|
|
endOffset: 880
|
|
});
|
|
|
|
// Test animation-range via timeline-scope.
|
|
test_animation_range({
|
|
rangeStart: 'exit 2em',
|
|
rangeEnd: 'exit 8em',
|
|
startOffset: 820,
|
|
endOffset: 880
|
|
}, template_with_scope, '(scoped)');
|
|
|
|
test_animation_range({
|
|
rangeStart: 'scroll 100px',
|
|
rangeEnd: 'scroll 800px',
|
|
startOffset: 100,
|
|
endOffset: 800
|
|
});
|
|
|
|
</script>
|