1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
|
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="help" src="https://www.w3.org/TR/scroll-animations-1/#named-range-animation-declaration">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/web-animations/testcommon.js"></script>
<script src="/web-animations/resources/keyframe-utils.js"></script>
<script src="support/testcommon.js"></script>
<script src="/scroll-animations/scroll-timelines/testcommon.js"></script>
<title>Programmatic API overrides animation-range-*</title>
</head>
<style type="text/css">
#scroller {
border: 10px solid lightgray;
overflow-y: scroll;
overflow-x: hidden;
width: 300px;
height: 200px;
}
@keyframes anim {
from { margin-left: 0px; }
to { margin-left: 100px; }
}
#target {
margin: 800px 0px;
width: 100px;
height: 100px;
z-index: -1;
background-color: green;
}
.animate {
animation: anim auto linear;
view-timeline: --timeline;
animation-timeline: --timeline;
animation-range-start: entry 0%;
animation-range-end: entry 100%;
}
</style>
<body>
<div id=scroller>
<div id=target></div>
</div>
</body>
<script type="text/javascript">
async function runTest() {
function startAnimation(t) {
target.classList.add('animate');
t.add_cleanup(async () => {
target.classList.remove('animate');
await waitForNextFrame();
});
return target.getAnimations()[0];
}
promise_test(async t => {
// Points of interest:
// entry 0% @ 600
// entry 100% / contain 0% @ 700
// exit 0% / contain 100% @ 800
// exit 100% @ 900
const anim = startAnimation(t);
await anim.ready;
scroller.scrollTop = 650;
await waitForNextFrame();
// Timline time = (scroll pos - cover 0%) / (cover 100% - cover 0%) * 100%
// = (650 - 600)/(900 - 600) * 100% = 100/6%
assert_percents_equal(anim.timeline.currentTime, 100/6,
'timeline\'s current time before style change');
assert_percents_equal(anim.startTime, 0,
'animation\'s start time before style change');
// Range start of entry 0% aligns with timeline start. Thus, animation's
// and timeline's current time are equal.
assert_percents_equal(anim.currentTime, 100/6,
'animation\'s current time before style change');
// Iteration duration =
// (range end - range start) / (cover 100% - cover 0%) * 100%
// = (700 - 600) / (900 - 600) = 33.3333%
assert_percents_equal(anim.effect.getComputedTiming().duration,
100/3,
'iteration duration before first style change');
assert_equals(getComputedStyle(target).marginLeft, '50px',
'margin-left before style change');
// Step 1: Set the range end programmatically and range start via CSS.
// The start time will be respected since not previously set via the
// animation API.
await runAndWaitForFrameUpdate(() => {
anim.rangeEnd = 'contain 100%';
target.style.animationRangeStart = 'entry 50%';
});
// Animation range does not affect timeline's currentTime.
assert_percents_equal(
anim.timeline.currentTime, 100/6,
'timeline\'s current time after first set of range updates');
assert_percents_equal(
anim.startTime, 100/6,
'animation\'s start time after first set of range updates');
// Scroll position aligns with range start.
assert_percents_equal(
anim.currentTime, 0,
'animation\'s current time after first set of range updates');
// Iteration duration =
// (range end - range start) / (cover 100% - cover 0%) * 100%
// = (800 - 650) / (900 - 600) = 50%
assert_percents_equal(
anim.effect.getComputedTiming().duration, 50,
'iteration duration after first style change');
assert_equals(getComputedStyle(target).marginLeft, '0px',
'margin-left after first set of range updates');
// Step 2: Programmatically set the range start.
// Scroll position is current at entry 50%, thus the animation's current
// time is negative.
await runAndWaitForFrameUpdate(() => {
anim.rangeStart = 'contain 0%';
});
// animation current time =
// (scroll pos - range start) / (cover 100% - cover 0%) * 100%
// = (650 - 700) / (900 - 600) * 100% = -100/6%
assert_percents_equal(
anim.currentTime, -100/6,
'animation\'s current time after second set of range updates');
// Iteration duration =
// (range end - range start) / (cover 100% - cover 0%) * 100%
// = (800 - 700) / (900 - 600) = 33.3333%
assert_percents_equal(
anim.effect.getComputedTiming().duration, 100/3,
'iteration duration after second style change');
assert_equals(getComputedStyle(target).marginLeft, '0px',
'margin-left after second set of range updates');
// Jump to contain / cover 50%
scroller.scrollTop = 750;
await waitForNextFrame();
// animation current time =
// (scroll pos - range start) / (cover 100% - cover 0%) * 100%
// = (750 - 700) / (900 - 600) * 100% = 100/6%
assert_percents_equal(
anim.currentTime, 100/6,
'animation\'s current time after bumping scroll position');
assert_approx_equals(parseFloat(getComputedStyle(target).marginLeft), 50, 0.125);
// Step 3: Try to update the range start via CSS. This change must be
// ignored since previously set programmatically.
await runAndWaitForFrameUpdate(() => {
target.style.animationRangeStart = "entry 50%";
});
assert_percents_equal(
anim.currentTime, 100/6,
'Current time unchanged after change to ignored CSS property');
assert_approx_equals(parseFloat(getComputedStyle(target).marginLeft), 50, 0.125,
'Margin-left unaffected by change to ignored CSS property');
}, 'Animation API call rangeStart overrides animation-range-start');
promise_test(async t => {
const anim = startAnimation(t);
await anim.ready;
scroller.scrollTop = 650;
await waitForNextFrame();
// Step 1: Set the range start programmatically and range end via CSS.
// The start time will be respected since not previously set via the
// animation API.
await runAndWaitForFrameUpdate(() => {
anim.rangeStart = "entry 50%";
target.style.animationRangeEnd = "contain 100%";
});
assert_percents_equal(
anim.timeline.currentTime, 100/6,
'timeline\'s current time after first set of range updates');
assert_percents_equal(
anim.startTime, 100/6,
'animation\'s start time after first set of range updates');
assert_percents_equal(
anim.currentTime, 0,
'animation\'s current time after first set of range updates');
assert_percents_equal(
anim.effect.getComputedTiming().duration, 50,
'iteration duration after first style change');
assert_equals(getComputedStyle(target).marginLeft, "0px",
'margin-left after first set of range updates');
// Step 2: Programmatically set the range.
// Scroll position is current at entry 50%, thus the animation's current
// time is negative.
await runAndWaitForFrameUpdate(() => {
anim.rangeStart = "contain 0%";
anim.rangeEnd = "contain 100%";
});
assert_percents_equal(
anim.currentTime, -100/6,
'animation\'s current time after second set of range updates');
assert_percents_equal(
anim.effect.getComputedTiming().duration, 100/3,
'iteration duration after second style change');
assert_equals(getComputedStyle(target).marginLeft, "0px",
'margin-left after second set of range updates');
// Jump to contain / cover 50%
scroller.scrollTop = 750;
await waitForNextFrame();
assert_percents_equal(
anim.currentTime, 100/6,
'animation\'s current time after bumping scroll position');
assert_approx_equals(parseFloat(getComputedStyle(target).marginLeft), 50, 0.125);
// Step 3: Try to update the range end via CSS. This change must be
// ignored since previously set programmatically.
await runAndWaitForFrameUpdate(() => {
target.style.animationRangeEnd = "cover 100%";
});
assert_percents_equal(
anim.currentTime, 100/6,
'Current time unchanged after change to ignored CSS property');
assert_approx_equals(parseFloat(getComputedStyle(target).marginLeft), 50, 0.125,
'Margin-left unaffected by change to ignored CSS property');
}, 'Animation API call rangeEnd overrides animation-range-end');
}
window.onload = runTest;
</script>
|