animation-trigger-state.tentative.html (7513B)
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <link rel="help" src="https://drafts.csswg.org/css-animations-2/#animation-trigger"> 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="/dom/events/scrolling/scroll_support.js"></script> 9 <script src="support/support.js"></script> 10 </head> 11 <body> 12 <style> 13 @keyframes myAnim { 14 from { transform: scaleX(1); } 15 to { transform: scaleX(5); } 16 } 17 .subject, .target { 18 height: 50px; 19 width: 50px; 20 background-color: red; 21 } 22 .target { 23 animation: myAnim linear 0.5s both; 24 } 25 26 #scroll_target { 27 animation-trigger: --scrolltrigger play-once pause; 28 timeline-trigger: --scrolltrigger scroll() 150px 200px; 29 } 30 #view_target { 31 animation-trigger: --viewtrigger play-once pause; 32 timeline-trigger: --viewtrigger view() 150px 200px; 33 } 34 #deferred_target { 35 animation-trigger: --deferredtrigger play-once pause; 36 } 37 #deferred_subject { 38 view-timeline: --viewtimeline; 39 timeline-trigger: --deferredtrigger --viewtimeline 150px 200px; 40 } 41 42 .scroller { 43 overflow-y: scroll; 44 height: 500px; 45 width: 500px; 46 border: solid 1px; 47 position: relative; 48 } 49 #wrapper { 50 timeline-scope: --viewtimeline; 51 } 52 #space { 53 width: 50px; 54 height: 600px; 55 } 56 </style> 57 <div id="wrapper"> 58 <div id="scroll_scroller" class="scroller"> 59 <div id="space"></div> 60 <div id="scroll_target" class="subject target" tabindex="0"></div> 61 <div id="space"></div> 62 </div> 63 <div id="view_scroller" class="scroller"> 64 <div id="space"></div> 65 <div id="view_target" class="subject target" tabindex="0"></div> 66 <div id="space"></div> 67 </div> 68 <div id="deferred_scroller" class="scroller"> 69 <div id="space"></div> 70 <div id="deferred_subject" class="subject" tabindex="0"></div> 71 <div id="space"></div> 72 </div> 73 <div id="deferred_target" class="target" tabindex="0"></div> 74 </div> 75 <script> 76 async function testStateAnimationTrigger(test, rangeBoundaries) { 77 // Just short of the trigger range start, no trigger action expected. 78 await testAnimationTrigger(test, () => { 79 return rangeBoundaries.exitTriggerRangeAbove(); 80 }, target, ["animationstart", "animationend"], [false, false]); 81 82 // This skips the trigger range and should not play the animation. 83 await testAnimationTrigger(test, () => { 84 return rangeBoundaries.exitTriggerRangeBelow(); 85 }, target, ["animationstart", "animationend"], [false, false]); 86 87 const initial_transform = getComputedStyle(target).transform; 88 // This is a state trigger, entering the trigger range plays the 89 // animation. 90 await testAnimationTrigger(test, async () => { 91 // Enter the range. 92 await rangeBoundaries.enterTriggerRange(); 93 await waitForAnimationFrames(5); 94 // Expect some progress. 95 assert_not_equals(getComputedStyle(target).transform, 96 initial_transform); 97 // Exit the range, which should pause the animation. 98 return rangeBoundaries.exitExitRangeBelow(); 99 }, target, ["animationstart", "animationend", "animationcancel"], 100 [true, false, false]); 101 let partial_transform = getComputedStyle(target).transform; 102 103 // Wait a few frames, then check that the animation is still paused. 104 await waitForAnimationFrames(5); 105 assert_equals(getComputedStyle(target).transform, partial_transform); 106 107 // This enters the trigger range and should continue the animation. 108 // Let it play till the end. 109 await testAnimationTrigger(test, () => { 110 return rangeBoundaries.enterTriggerRange(); 111 }, target, ["animationstart", "animationend"], [false, true]); 112 let final_transform = getComputedStyle(target).transform; 113 114 // Exit the range. This should have no effect as the animation has 115 // already finished. 116 await testAnimationTrigger(test, async () => { 117 return rangeBoundaries.exitExitRangeAbove(); 118 }, target, ["animationstart", "animationend", "animationcancel"], 119 [false, false, false]); 120 121 // Wait a few frames. Exiting the animation should make no difference; 122 // the animation is already finished. 123 await waitForAnimationFrames(5); 124 assert_equals(getComputedStyle(target).transform, final_transform); 125 126 // Enter the range again. This should make no difference. The animation 127 // is already finished. 128 await testAnimationTrigger(test, async () => { 129 return rangeBoundaries.enterTriggerRange(); 130 }, target, ["animationstart", "animationend", "animationcancel"], 131 [false, false, false]); 132 133 // Wait a few frames. Check the animation is still at the end. 134 await waitForAnimationFrames(5); 135 assert_equals(getComputedStyle(target).transform, final_transform); 136 } 137 138 // The trigger and exit ranges are the same for this test. 139 const CSS_TRIGGER_START_PX = 150; 140 const CSS_TRIGGER_END_PX = 200; 141 142 promise_test(async (test) => { 143 scroller = scroll_scroller; 144 target = scroll_target; 145 146 const rangeBoundaries = getRangeBoundariesForTest(CSS_TRIGGER_START_PX, 147 CSS_TRIGGER_END_PX, 148 CSS_TRIGGER_START_PX, 149 CSS_TRIGGER_END_PX, 150 scroller); 151 await testStateAnimationTrigger(test, rangeBoundaries); 152 }, "once animation triggered via scroll() timeline."); 153 154 promise_test(async (test) => { 155 scroller = view_scroller; 156 target = view_target; 157 158 const COVER_START_OFFSET = 100; 159 160 const rangeBoundaries = getRangeBoundariesForTest( 161 COVER_START_OFFSET + CSS_TRIGGER_START_PX, 162 COVER_START_OFFSET + CSS_TRIGGER_END_PX, 163 COVER_START_OFFSET + CSS_TRIGGER_START_PX, 164 COVER_START_OFFSET + CSS_TRIGGER_END_PX, 165 scroller); 166 await testStateAnimationTrigger(test, rangeBoundaries); 167 }, "once animation triggered via view() timeline."); 168 169 promise_test(async (test) => { 170 scroller = deferred_scroller; 171 target = deferred_target; 172 173 const COVER_START_OFFSET = 100; 174 175 const rangeBoundaries = getRangeBoundariesForTest( 176 COVER_START_OFFSET + CSS_TRIGGER_START_PX, 177 COVER_START_OFFSET + CSS_TRIGGER_END_PX, 178 COVER_START_OFFSET + CSS_TRIGGER_START_PX, 179 COVER_START_OFFSET + CSS_TRIGGER_END_PX, 180 scroller); 181 await testStateAnimationTrigger(test, rangeBoundaries); 182 }, "once animation triggered via deferred (view) timeline."); 183 </script> 184 </body> 185 </html>