get-keyframes-with-timeline-offset.html (8705B)
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <!-- TODO(kevers): Insert link once resolutions present in spec --> 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="/web-animations/resources/keyframe-utils.js"></script> 10 <script src="support/testcommon.js"></script> 11 <title>Reported keyframes containing timeline offset</title> 12 </head> 13 <style type="text/css"> 14 #scroller { 15 border: 10px solid lightgray; 16 overflow-y: scroll; 17 overflow-x: hidden; 18 width: 300px; 19 height: 200px; 20 } 21 #target { 22 margin: 800px 10px; 23 width: 100px; 24 height: 100px; 25 z-index: -1; 26 background-color: green; 27 } 28 </style> 29 <body> 30 <div id=scroller> 31 <div id=target></div> 32 </div> 33 </body> 34 <script type="text/javascript"> 35 async function runTest() { 36 function createAnimation(t, keyframes, use_view_timeline = true) { 37 const options = { 38 rangeStart: { rangeName: 'contain', offset: CSS.percent(0) }, 39 rangeEnd: { rangeName: 'contain', offset: CSS.percent(100) }, 40 duration: 'auto', 41 fill: 'both' 42 }; 43 if (use_view_timeline) { 44 options.timeline = new ViewTimeline( { subject: target }); 45 } 46 const anim = target.animate(keyframes, options); 47 t.add_cleanup(() => { 48 anim.cancel(); 49 }); 50 return anim; 51 } 52 53 promise_test(async t => { 54 let anim = createAnimation(t, [ 55 { offset: "contain 25%", marginLeft: "0px", opacity: "0" }, 56 { offset: "contain 75%", marginRight: "0px", opacity: "1" } 57 ]); 58 let frames = anim.effect.getKeyframes(); 59 let expected = [ 60 { offset: { rangeName: 'contain', offset: CSS.percent(25) }, 61 computedOffset: 0.25, easing: "linear", composite: "auto", 62 marginLeft: "0px", opacity: "0" }, 63 { offset: { rangeName: 'contain', offset: CSS.percent(75) }, 64 computedOffset: 0.75, easing: "linear", composite: "auto", 65 marginRight: "0px", opacity: "1" } 66 ]; 67 assert_frame_lists_equal(frames, expected); 68 }, 'Report specified timeline offsets'); 69 70 promise_test(async t => { 71 let anim = createAnimation(t, [ 72 { offset: "cover 0%", marginLeft: "0px", opacity: "0" }, 73 { offset: "cover 100%", marginRight: "0px", opacity: "1" } 74 ]); 75 let frames = anim.effect.getKeyframes(); 76 let expected = [ 77 { offset: { rangeName: 'cover', offset: CSS.percent(0) }, 78 computedOffset: -1, easing: "linear", composite: "auto", 79 marginLeft: "0px", opacity: "0" }, 80 { offset: { rangeName: 'cover', offset: CSS.percent(100) }, 81 computedOffset: 2, easing: "linear", composite: "auto", 82 marginRight: "0px", opacity: "1" } 83 ]; 84 assert_frame_lists_equal(frames, expected); 85 }, 'Computed offsets can be outside [0,1] for keyframes with timeline ' + 86 'offsets'); 87 88 promise_test(async t => { 89 let anim = createAnimation(t, [ 90 { offset: "cover -100%", opacity: "0" }, 91 { offset: "cover 200%", opacity: "1" }, 92 ]); 93 let frames = anim.effect.getKeyframes(); 94 let expected = [ 95 { offset: { rangeName: 'cover', offset: CSS.percent(-100) }, 96 computedOffset: -4, easing: "linear", composite: "auto", 97 opacity: "0" }, 98 { offset: { rangeName: 'cover', offset: CSS.percent(200) }, 99 computedOffset: 5, easing: "linear", composite: "auto", 100 opacity: "1" } 101 ]; 102 assert_frame_lists_equal(frames, expected); 103 }, 'Offsets can be outside [0%,100%] for keyframes with timeline range names'); 104 105 promise_test(async t => { 106 let anim = createAnimation(t, [ 107 { offset: "contain 75%", marginLeft: "0px", opacity: "0" }, 108 { offset: "contain 25%", marginRight: "0px", opacity: "1" } 109 ]); 110 let frames = anim.effect.getKeyframes(); 111 let expected = [ 112 { offset: { rangeName: 'contain', offset: CSS.percent(75) }, 113 computedOffset: 0.75, easing: "linear", composite: "auto", 114 marginLeft: "0px", opacity: "0" }, 115 { offset: { rangeName: 'contain', offset: CSS.percent(25) }, 116 computedOffset: 0.25, easing: "linear", composite: "auto", 117 marginRight: "0px", opacity: "1" } 118 ]; 119 assert_frame_lists_equal(frames, expected); 120 }, 'Retain specified ordering of keyframes with timeline offsets'); 121 122 promise_test(async t => { 123 let anim = createAnimation(t, [ 124 { offset: "cover 0%", marginLeft: "0px", opacity: "0" }, 125 { offset: "cover 100%", marginRight: "0px", opacity: "1" } 126 ], /* use_view_timeline */ false); 127 let frames = anim.effect.getKeyframes(); 128 let expected = [ 129 { offset: { rangeName: 'cover', offset: CSS.percent(0) }, 130 computedOffset: null, easing: "linear", composite: "auto", 131 marginLeft: "0px", opacity: "0" }, 132 { offset: { rangeName: 'cover', offset: CSS.percent(100) }, 133 computedOffset: null, easing: "linear", composite: "auto", 134 marginRight: "0px", opacity: "1" } 135 ]; 136 assert_frame_lists_equal(frames, expected); 137 }, 'Include unreachable keyframes'); 138 139 140 promise_test(async t => { 141 let anim = createAnimation(t, [ 142 { offset: "cover 0%", marginLeft: "0px", opacity: 0 }, 143 { offset: "cover 100%", marginRight: "0px", opacity: 1 }, 144 { opacity: 0 }, 145 { opacity: 0.5 }, 146 { opacity: 1.0 } 147 ]); 148 let frames = anim.effect.getKeyframes(); 149 let expected = [ 150 { offset: { rangeName: 'cover', offset: CSS.percent(0) }, 151 computedOffset: -1, easing: "linear", composite: "auto", 152 marginLeft: "0px", opacity: "0" }, 153 { offset: { rangeName: 'cover', offset: CSS.percent(100) }, 154 computedOffset: 2, easing: "linear", composite: "auto", 155 marginRight: "0px", opacity: "1" }, 156 { offset: null, computedOffset: 0, easing: "linear", composite: "auto", 157 opacity: "0" }, 158 { offset: null, computedOffset: 0.5, easing: "linear", 159 composite: "auto", opacity: "0.5" }, 160 { offset: null, computedOffset: 1.0, easing: "linear", 161 composite: "auto", opacity: "1" } 162 ]; 163 assert_frame_lists_equal(frames, expected); 164 165 anim = createAnimation(t, [ 166 { opacity: 0 }, 167 { offset: "cover 0%", marginLeft: "0px", opacity: 0 }, 168 { opacity: 0.5 }, 169 { offset: "cover 100%", marginRight: "0px", opacity: 1 }, 170 { opacity: 1.0 } 171 ]); 172 frames = anim.effect.getKeyframes(); 173 expected = [ 174 { offset: null, computedOffset: 0, easing: "linear", composite: "auto", 175 opacity: "0" }, 176 { offset: { rangeName: 'cover', offset: CSS.percent(0) }, 177 computedOffset: -1, easing: "linear", composite: "auto", 178 marginLeft: "0px", opacity: "0" }, 179 { offset: null, computedOffset: 0.5, easing: "linear", 180 composite: "auto", opacity: "0.5" }, 181 { offset: { rangeName: 'cover', offset: CSS.percent(100) }, 182 computedOffset: 2, easing: "linear", composite: "auto", 183 marginRight: "0px", opacity: "1" }, 184 { offset: null, computedOffset: 1.0, easing: "linear", 185 composite: "auto", opacity: "1" } 186 ]; 187 assert_frame_lists_equal(frames, expected); 188 189 anim = createAnimation(t, [ 190 { opacity: 0.2, offset: 0.2 }, 191 { offset: "cover 0%", marginLeft: "0px", opacity: 0 }, 192 { opacity: 0.4 }, 193 { opacity: 0.6 }, 194 { offset: "cover 100%", marginRight: "0px", opacity: 1 }, 195 { opacity: 0.8, offset: 0.8 } 196 ]); 197 frames = anim.effect.getKeyframes(); 198 expected = [ 199 { offset: 0.2, computedOffset: 0.2, easing: "linear", composite: "auto", 200 opacity: "0.2" }, 201 { offset: { rangeName: 'cover', offset: CSS.percent(0) }, 202 computedOffset: -1, easing: "linear", composite: "auto", 203 marginLeft: "0px", opacity: "0" }, 204 { offset: null, computedOffset: 0.4, easing: "linear", 205 composite: "auto", opacity: "0.4" }, 206 { offset: null, computedOffset: 0.6, easing: "linear", 207 composite: "auto", opacity: "0.6" }, 208 { offset: { rangeName: 'cover', offset: CSS.percent(100) }, 209 computedOffset: 2, easing: "linear", composite: "auto", 210 marginRight: "0px", opacity: "1" }, 211 { offset: 0.8, computedOffset: 0.8, easing: "linear", composite: "auto", 212 opacity: "0.8" } 213 ]; 214 assert_frame_lists_equal(frames, expected); 215 }, 'Mix of computed and timeline offsets.'); 216 } 217 218 window.onload = runTest; 219 </script> 220 </html>