scroll-timeline-range.html (5232B)
1 <!DOCTYPE html> 2 <title>Scroll timelines and animation attachment ranges</title> 3 <link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#named-timeline-range"> 4 <link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#animation-range"> 5 <script src="/resources/testharness.js"></script> 6 <script src="/resources/testharnessreport.js"></script> 7 <script src="/web-animations/testcommon.js"></script> 8 <script src="support/testcommon.js"></script> 9 <style> 10 #scroller { 11 overflow-y: scroll; 12 width: 200px; 13 height: 200px; 14 scroll-timeline: --t1; 15 } 16 .spacer { 17 height: 1100px; 18 } 19 #target { 20 height: 100px; 21 width: 0; 22 font-size: 10px; 23 background-color: green; 24 } 25 @keyframes grow { 26 to { width: 200px } 27 } 28 .anim-1 { 29 animation: auto grow linear; 30 animation-timeline: --t1; 31 animation-range-start: 25%; 32 animation-range-end: 75%; 33 } 34 .anim-2 { 35 animation: auto grow linear; 36 animation-timeline: --t1; 37 animation-range-start: 40px; 38 animation-range-end: 700px; 39 } 40 .anim-3 { 41 animation: auto grow linear; 42 animation-timeline: --t1; 43 animation-range-start: calc(30% + 40px); 44 animation-range-end: calc(70% - 20px); 45 } 46 .anim-4 { 47 animation: auto grow linear; 48 animation-timeline: --t1; 49 animation-range-start: 5em; 50 animation-range-end: calc(100% - 5em); 51 } 52 53 </style> 54 <div id=scroller> 55 <div id=target></div> 56 <div class=spacer></div> 57 </div> 58 <script> 59 // Test via web-animation API. 60 61 async function test_range_waapi(t, options) { 62 const timeline = new ScrollTimeline({source: scroller, axis: 'block'}); 63 const anim = 64 target.animate([{ width: "200px" }], 65 { 66 timeline: timeline, 67 rangeStart: options.rangeStart, 68 rangeEnd: options.rangeEnd 69 }); 70 t.add_cleanup(() => { 71 anim.cancel(); 72 }); 73 await anim.ready; 74 await runAndWaitForFrameUpdate(() => { 75 scroller.scrollTop = 600; 76 }); 77 78 const expectedProgress = 79 (600 - options.startOffset) / (options.endOffset - options.startOffset); 80 assert_approx_equals(anim.effect.getComputedTiming().progress, 81 expectedProgress, 0.001); 82 } 83 84 promise_test(async t => { 85 await test_range_waapi(t, { 86 rangeStart: "25%", 87 rangeEnd: "75%", 88 startOffset: 250, 89 endOffset: 750 90 }); 91 }, 'Scroll timeline with percentage range [JavaScript API]'); 92 93 promise_test(async t => { 94 await test_range_waapi(t, { 95 rangeStart: "40px", 96 rangeEnd: "700px", 97 startOffset: 40, 98 endOffset: 700 99 }); 100 }, 'Scroll timeline with px range [JavaScript API]'); 101 102 promise_test(async t => { 103 await test_range_waapi(t, { 104 rangeStart: "calc(30% + 40px)", 105 rangeEnd: "calc(70% - 20px)", 106 startOffset: 340, 107 endOffset: 680 108 }); 109 }, 'Scroll timeline with calculated range [JavaScript API]'); 110 111 promise_test(async t => { 112 t.add_cleanup(() => { 113 target.style.fontSize = ''; 114 }); 115 await test_range_waapi(t, { 116 rangeStart: "5em", 117 rangeEnd: "calc(100% - 5em)", 118 startOffset: 50, 119 endOffset: 950 120 }); 121 target.style.fontSize = '20px'; 122 await waitForNextFrame(); 123 const anim = target.getAnimations()[0]; 124 const expectedProgress = (600 - 100) / (900 - 100); 125 assert_approx_equals(anim.effect.getComputedTiming().progress, 126 expectedProgress, 0.001); 127 }, 'Scroll timeline with EM range [JavaScript API]'); 128 129 // Test via CSS. 130 async function test_range_css(t, options) { 131 t.add_cleanup(() => { 132 target.classList.remove(options.animation); 133 }); 134 target.classList.add(options.animation); 135 const anim = target.getAnimations()[0]; 136 await anim.ready; 137 scroller.scrollTop = 600; 138 await waitForNextFrame(); 139 140 const expectedProgress = 141 (600 - options.startOffset) / (options.endOffset - options.startOffset); 142 assert_approx_equals(anim.effect.getComputedTiming().progress, 143 expectedProgress, 0.001); 144 } 145 146 promise_test(async t => { 147 await test_range_css(t, { 148 animation: "anim-1", 149 startOffset: 250, 150 endOffset: 750 151 }); 152 }, 'Scroll timeline with percentage range [CSS]'); 153 154 promise_test(async t => { 155 await test_range_css(t, { 156 animation: "anim-2", 157 startOffset: 40, 158 endOffset: 700 159 }); 160 }, 'Scroll timeline with px range [CSS]'); 161 162 promise_test(async t => { 163 await test_range_css(t, { 164 animation: "anim-3", 165 startOffset: 340, 166 endOffset: 680 167 }); 168 }, 'Scroll timeline with calculated range [CSS]'); 169 170 promise_test(async t => { 171 t.add_cleanup(() => { 172 target.style.fontSize = ''; 173 }); 174 await test_range_css(t, { 175 animation: "anim-4", 176 startOffset: 50, 177 endOffset: 950 178 }); 179 target.style.fontSize = '20px'; 180 await waitForNextFrame(); 181 const anim = target.getAnimations()[0]; 182 const expectedProgress = (600 - 100) / (900 - 100); 183 assert_approx_equals(anim.effect.getComputedTiming().progress, 184 expectedProgress, 0.001); 185 }, 'Scroll timeline with EM range [CSS]'); 186 </script>