animation-trigger-repeat.tentative.html (6431B)
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-forwards reset; 28 timeline-trigger: --scrolltrigger scroll() 250px 300px / 200px 350px; 29 } 30 #view_target { 31 animation-trigger: --viewtrigger play-forwards reset; 32 timeline-trigger: --viewtrigger view() 250px 300px / 200px 350px; 33 } 34 #deferred_target { 35 animation-trigger: --deferredtrigger play-forwards reset; 36 } 37 #deferred_subject { 38 view-timeline: --viewtimeline; 39 timeline-trigger: --deferredtrigger --viewtimeline 250px 300px / 200px 350px; 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 // // Each test case sets these. 77 // let scroller; 78 // let target; 79 80 async function testRepeatAnimationTrigger(test, rangeBoundaries) { 81 const initial_transform = getComputedStyle(target).transform; 82 // Just short of the trigger range start, no trigger action expected. 83 await testAnimationTrigger(test, () => { 84 return rangeBoundaries.exitTriggerRangeAbove(); 85 }, target, ["animationstart", "animationend"], [false, false]); 86 87 // This skips the trigger range and should not play the animation. 88 await testAnimationTrigger(test, () => { 89 return rangeBoundaries.exitTriggerRangeBelow(); 90 }, target, ["animationstart", "animationend"], [false, false]); 91 92 // This enters the trigger range and should play the animation. 93 await testAnimationTrigger(test, () => { 94 return rangeBoundaries.enterTriggerRange(); 95 }, target, ["animationstart", "animationend"], [true, true]); 96 97 // This is a repeat trigger, exiting the exit range resets the 98 // animation. By inspecting style.transform, we should see that the 99 // animation was reset. 100 await testAnimationTrigger(test, () => { 101 return rangeBoundaries.exitExitRangeAbove(); 102 }, target, ["animationstart", "animationend", "animationcancel"], 103 [false, false, false]); 104 assert_equals(getComputedStyle(target).transform, initial_transform); 105 106 // This is a repeat trigger, re-entering plays the animation. 107 await testAnimationTrigger(test, async () => { 108 // Enter the range. 109 await rangeBoundaries.enterTriggerRange(); 110 await waitForAnimationFrames(5); 111 // Exit the range. 112 return rangeBoundaries.exitExitRangeBelow(); 113 }, target, ["animationstart", "animationend", "animationcancel"], 114 [true, false, false]); 115 } 116 117 const CSS_TRIGGER_START_PX = 250; 118 const CSS_TRIGGER_END_PX = 300; 119 const CSS_EXIT_START_PX = 200; 120 const CSS_EXIT_END_PX = 350; 121 122 promise_test(async (test) => { 123 scroller = scroll_scroller; 124 target = scroll_target; 125 126 const rangeBoundaries = getRangeBoundariesForTest(CSS_TRIGGER_START_PX, 127 CSS_TRIGGER_END_PX, 128 CSS_EXIT_START_PX, 129 CSS_EXIT_END_PX, 130 scroller); 131 await testRepeatAnimationTrigger(test, rangeBoundaries); 132 }, "repeat animation triggered via scroll() timeline."); 133 134 promise_test(async (test) => { 135 scroller = view_scroller; 136 target = view_target; 137 138 const COVER_START_OFFSET = 100; 139 140 const rangeBoundaries = getRangeBoundariesForTest( 141 COVER_START_OFFSET + CSS_TRIGGER_START_PX, 142 COVER_START_OFFSET + CSS_TRIGGER_END_PX, 143 COVER_START_OFFSET + CSS_EXIT_START_PX, 144 COVER_START_OFFSET + CSS_EXIT_END_PX, 145 scroller); 146 await testRepeatAnimationTrigger(test, rangeBoundaries); 147 }, "repeat animation triggered via view() timeline."); 148 149 promise_test(async (test) => { 150 scroller = deferred_scroller; 151 target = deferred_target; 152 153 const COVER_START_OFFSET = 100; 154 155 const rangeBoundaries = getRangeBoundariesForTest( 156 COVER_START_OFFSET + CSS_TRIGGER_START_PX, 157 COVER_START_OFFSET + CSS_TRIGGER_END_PX, 158 COVER_START_OFFSET + CSS_EXIT_START_PX, 159 COVER_START_OFFSET + CSS_EXIT_END_PX, 160 scroller); 161 await testRepeatAnimationTrigger(test, rangeBoundaries); 162 }, "repeat animation triggered via deferred (view) timeline."); 163 </script> 164 </body> 165 </html>