progress-based-animation-animation-longhand-properties.tentative.html (8989B)
1 <!DOCTYPE html> 2 <title>The various animation longhands with progress based animations</title> 3 <link rel="help" src="https://drafts.csswg.org/css-animations-2"> 4 <link rel="help" src="https://github.com/w3c/csswg-drafts/issues/4862"> 5 <link rel="help" src="https://github.com/w3c/csswg-drafts/issues/6674"> 6 <script src="/resources/testharness.js"></script> 7 <script src="/resources/testharnessreport.js"></script> 8 <script src="/web-animations/testcommon.js"></script> 9 <script src="support/testcommon.js"></script> 10 <style> 11 @keyframes anim { 12 from { translate: 0px; } 13 to { translate: 100px; } 14 } 15 #container { 16 width: 300px; 17 height: 300px; 18 overflow: scroll; 19 } 20 #target { 21 width: 100px; 22 height: 100px; 23 translate: none; 24 } 25 </style> 26 <body> 27 <div id="log"></div> 28 <script> 29 "use strict"; 30 31 setup(assert_implements_animation_timeline); 32 33 const assert_translate_equals = (target, expected, description) => { 34 assert_approx_equals(parseFloat(getComputedStyle(target).translate), parseFloat(expected), 0.0001, description); 35 }; 36 37 const createTargetAndScroller = function(t) { 38 let container = document.createElement('div'); 39 container.id = 'container'; 40 let target = document.createElement('div'); 41 target.id = 'target'; 42 let content = document.createElement('div'); 43 content.style.blockSize = '100%'; 44 45 // The height of target is 100px and the content is 100%, so the scroll range 46 // is [0, 100]. 47 48 // <div id='container'> 49 // <div id='target'></div> 50 // <div style='block-size: 100%;'></div> 51 // </div> 52 document.body.appendChild(container); 53 container.appendChild(target); 54 container.appendChild(content); 55 56 if (t && typeof t.add_cleanup === 'function') { 57 t.add_cleanup(() => { 58 content.remove(); 59 target.remove(); 60 container.remove(); 61 }); 62 } 63 64 return [target, container]; 65 }; 66 67 async function scrollTop(element, value) { 68 element.scrollTop = value; 69 await waitForNextFrame(); 70 } 71 72 // ------------------------------ 73 // Test animation-duration 74 // ------------------------------ 75 76 promise_test(async t => { 77 let [target, scroller] = createTargetAndScroller(t); 78 await runAndWaitForFrameUpdate(() => { 79 target.style.animation = '10s linear anim'; 80 target.style.animationTimeline = 'scroll(nearest)'; 81 }); 82 83 await scrollTop(scroller, 25); // [0, 100]. 84 assert_translate_equals(target, '25px'); 85 }, 'animation-duration'); 86 87 promise_test(async t => { 88 let [target, scroller] = createTargetAndScroller(t); 89 target.style.animation = '0s linear anim forwards'; 90 target.style.animationTimeline = 'scroll(nearest)'; 91 92 await scrollTop(scroller, 25); // [0, 100]. 93 assert_translate_equals(target, '100px'); 94 }, 'animation-duration: 0s'); 95 96 97 // ------------------------------ 98 // Test animation-iteration-count 99 // ------------------------------ 100 101 promise_test(async t => { 102 let [target, scroller] = createTargetAndScroller(t); 103 await runAndWaitForFrameUpdate(() => { 104 target.style.animation = '10s linear anim'; 105 target.style.animationTimeline = 'scroll(nearest)'; 106 }); 107 108 await scrollTop(scroller, 25); // [0, 100]. 109 assert_translate_equals(target, '25px'); 110 111 // Let animation become 50% in the 1st iteration. 112 target.style.animationIterationCount = '2'; 113 await waitForCSSScrollTimelineStyle(); 114 assert_translate_equals(target, '50px'); 115 116 // Let animation become 0% in the 2nd iteration. 117 target.style.animationIterationCount = '4'; 118 await waitForCSSScrollTimelineStyle(); 119 assert_translate_equals(target, '0px'); 120 }, 'animation-iteration-count'); 121 122 promise_test(async t => { 123 let [target, scroller] = createTargetAndScroller(t); 124 await runAndWaitForFrameUpdate(() => { 125 target.style.animation = '10s linear anim forwards'; 126 target.style.animationTimeline = 'scroll(nearest)'; 127 target.style.animationIterationCount = '0'; 128 }); 129 130 await scrollTop(scroller, 25); // [0, 100]. 131 assert_translate_equals(target, '0px'); 132 }, 'animation-iteration-count: 0'); 133 134 promise_test(async t => { 135 let [target, scroller] = createTargetAndScroller(t); 136 await runAndWaitForFrameUpdate(() => { 137 target.style.animation = '10s linear anim forwards'; 138 target.style.animationTimeline = 'scroll(nearest)'; 139 target.style.animationIterationCount = 'infinite'; 140 }); 141 142 await scrollTop(scroller, 25); // [0, 100]. 143 assert_translate_equals(target, '100px'); 144 }, 'animation-iteration-count: infinite'); 145 146 147 // ------------------------------ 148 // Test animation-direction 149 // ------------------------------ 150 151 promise_test(async t => { 152 let [target, scroller] = createTargetAndScroller(t); 153 await runAndWaitForFrameUpdate(() => { 154 target.style.animation = '10s linear anim'; 155 target.style.animationTimeline = 'scroll(nearest)'; 156 }); 157 158 await scrollTop(scroller, 25) // [0, 100]. 159 assert_translate_equals(target, '25px'); 160 }, 'animation-direction: normal'); 161 162 promise_test(async t => { 163 let [target, scroller] = createTargetAndScroller(t); 164 await runAndWaitForFrameUpdate(() => { 165 target.style.animation = '10s linear anim'; 166 target.style.animationTimeline = 'scroll(nearest)'; 167 target.style.animationDirection = 'reverse'; 168 }); 169 170 await scrollTop(scroller, 25); // 25% in the reversing direction. 171 assert_translate_equals(target, '75px'); 172 }, 'animation-direction: reverse'); 173 174 promise_test(async t => { 175 let [target, scroller] = createTargetAndScroller(t); 176 await runAndWaitForFrameUpdate(() => { 177 target.style.animation = '10s linear anim'; 178 target.style.animationTimeline = 'scroll(nearest)'; 179 target.style.animationIterationCount = '2'; 180 target.style.animationDirection = 'alternate'; 181 }); 182 183 await scrollTop(scroller, 10); // 20% in the 1st iteration. 184 assert_translate_equals(target, '20px'); 185 186 await scrollTop(scroller, 60); // 20% in the 2nd iteration (reversing direction). 187 assert_translate_equals(target, '80px'); 188 }, 'animation-direction: alternate'); 189 190 promise_test(async t => { 191 let [target, scroller] = createTargetAndScroller(t); 192 await runAndWaitForFrameUpdate(() => { 193 target.style.animation = '10s linear anim'; 194 target.style.animationTimeline = 'scroll(nearest)'; 195 target.style.animationIterationCount = '2'; 196 target.style.animationDirection = 'alternate-reverse'; 197 }); 198 199 await scrollTop(scroller, 10); // 20% in the 1st iteration (reversing direction). 200 assert_translate_equals(target, '80px'); 201 202 await scrollTop(scroller, 60); // 20% in the 2nd iteration. 203 assert_translate_equals(target, '20px'); 204 }, 'animation-direction: alternate-reverse'); 205 206 207 // ------------------------------ 208 // Test animation-delay 209 // ------------------------------ 210 211 promise_test(async t => { 212 let [target, scroller] = createTargetAndScroller(t); 213 await runAndWaitForFrameUpdate(() => { 214 target.style.animation = '10s linear anim'; 215 target.style.animationTimeline = 'scroll(nearest)'; 216 }); 217 218 await scrollTop(scroller, 25); // [0, 100]. 219 assert_translate_equals(target, '25px'); 220 221 // (start delay: 10s) (duration: 10s) 222 // before active 223 // |--------------------|--------------------| 224 // 0px 50px 100px (The scroller) 225 // 0% 100% (The iteration progress) 226 227 // Let animation be in before phase. 228 target.style.animationDelay = '10s'; 229 target.style.animationDelayStart = '10s'; // crbug.com/1375994 230 assert_translate_equals(target, 'none'); 231 232 await scrollTop(scroller, 50); // The animation enters active phase. 233 assert_translate_equals(target, '0px'); 234 235 await scrollTop(scroller, 75); // The ieration progress is 50%. 236 assert_translate_equals(target, '50px'); 237 }, 'animation-delay with a positive value'); 238 239 promise_test(async t => { 240 let [target, scroller] = createTargetAndScroller(t); 241 await runAndWaitForFrameUpdate(() => { 242 target.style.animation = '10s linear anim'; 243 target.style.animationTimeline = 'scroll(nearest)'; 244 }); 245 246 // active 247 // |--------------------| 248 // 0px 100px (The scroller) 249 // 50% 100% (The iteration progress) 250 251 await scrollTop(scroller, 20); // [0, 100]. 252 target.style.animationDelay = '-5s'; 253 target.style.animationDelayStart = '-5s'; // crbug.com/1375994 254 await waitForCSSScrollTimelineStyle(); 255 assert_translate_equals(target, '60px'); 256 }, 'animation-delay with a negative value'); 257 258 259 // ------------------------------ 260 // Test animation-fill-mode 261 // ------------------------------ 262 263 promise_test(async t => { 264 let [target, scroller] = createTargetAndScroller(t); 265 await runAndWaitForFrameUpdate(() => { 266 target.style.animation = '10s linear anim'; 267 target.style.animationTimeline = 'scroll(nearest)'; 268 target.style.animationDelay = '10s'; 269 target.style.animationDelayStart = '10s'; // crbug.com/1375994 270 }); 271 272 await scrollTop(scroller, 25); 273 assert_translate_equals(target, 'none'); 274 275 target.style.animationFillMode = 'backwards'; 276 await waitForCSSScrollTimelineStyle(); 277 assert_translate_equals(target, '0px'); 278 }, 'animation-fill-mode'); 279 280 </script> 281 </body>