effect-value-iteration-composite-operation.html (36931B)
1 <!doctype html> 2 <meta charset=utf-8> 3 <title>The effect value of a keyframe effect: Applying the iteration composite 4 operation</title> 5 <link rel="help" href="https://drafts.csswg.org/web-animations/#the-effect-value-of-a-keyframe-animation-effect"> 6 <link rel="help" href="https://drafts.csswg.org/web-animations/#effect-accumulation-section"> 7 <script src=/resources/testharness.js></script> 8 <script src=/resources/testharnessreport.js></script> 9 <script src="../../testcommon.js"></script> 10 <div id="log"></div> 11 <script> 12 'use strict'; 13 14 test(t => { 15 const div = createDiv(t); 16 const anim = 17 div.animate({ alignContent: ['flex-start', 'flex-end'] }, 18 { duration: 100 * MS_PER_SEC, 19 easing: 'linear', 20 iterations: 10, 21 iterationComposite: 'accumulate' }); 22 23 anim.currentTime = anim.effect.getComputedTiming().duration / 2; 24 assert_equals(getComputedStyle(div).alignContent, 'flex-end', 25 'Animated align-content style at 50s of the first iteration'); 26 anim.currentTime = anim.effect.getComputedTiming().duration * 2; 27 assert_equals(getComputedStyle(div).alignContent, 'flex-start', 28 'Animated align-content style at 0s of the third iteration'); 29 anim.currentTime += anim.effect.getComputedTiming().duration / 2; 30 assert_equals(getComputedStyle(div).alignContent, 'flex-end', 31 'Animated align-content style at 50s of the third iteration'); 32 }, 'iteration composition of discrete type animation (align-content)'); 33 34 test(t => { 35 const div = createDiv(t); 36 const anim = 37 div.animate({ marginLeft: ['0px', '10px'] }, 38 { duration: 100 * MS_PER_SEC, 39 easing: 'linear', 40 iterations: 10, 41 iterationComposite: 'accumulate' }); 42 anim.pause(); 43 44 anim.currentTime = anim.effect.getComputedTiming().duration / 2; 45 assert_equals(getComputedStyle(div).marginLeft, '5px', 46 'Animated margin-left style at 50s of the first iteration'); 47 anim.currentTime = anim.effect.getComputedTiming().duration * 2; 48 assert_equals(getComputedStyle(div).marginLeft, '20px', 49 'Animated margin-left style at 0s of the third iteration'); 50 anim.currentTime += anim.effect.getComputedTiming().duration / 2; 51 assert_equals(getComputedStyle(div).marginLeft, '25px', 52 'Animated margin-left style at 50s of the third iteration'); 53 }, 'iteration composition of <length> type animation'); 54 55 test(t => { 56 const parent = createDiv(t); 57 parent.style.width = '100px'; 58 const div = createDiv(t); 59 parent.appendChild(div); 60 61 const anim = 62 div.animate({ width: ['0%', '50%'] }, 63 { duration: 100 * MS_PER_SEC, 64 easing: 'linear', 65 iterations: 10, 66 iterationComposite: 'accumulate' }); 67 anim.pause(); 68 69 anim.currentTime = anim.effect.getComputedTiming().duration / 2; 70 assert_equals(getComputedStyle(div).width, '25px', 71 'Animated width style at 50s of the first iteration'); 72 anim.currentTime = anim.effect.getComputedTiming().duration * 2; 73 assert_equals(getComputedStyle(div).width, '100px', 74 'Animated width style at 0s of the third iteration'); 75 anim.currentTime += anim.effect.getComputedTiming().duration / 2; 76 assert_equals(getComputedStyle(div).width, '125px', 77 'Animated width style at 50s of the third iteration'); 78 }, 'iteration composition of <percentage> type animation'); 79 80 test(t => { 81 const div = createDiv(t); 82 const anim = 83 div.animate({ color: ['rgb(0, 0, 0)', 'rgb(120, 120, 120)'] }, 84 { duration: 100 * MS_PER_SEC, 85 easing: 'linear', 86 iterations: 10, 87 iterationComposite: 'accumulate' }); 88 anim.pause(); 89 90 anim.currentTime = anim.effect.getComputedTiming().duration / 2; 91 assert_equals(getComputedStyle(div).color, 'rgb(60, 60, 60)', 92 'Animated color style at 50s of the first iteration'); 93 anim.currentTime = anim.effect.getComputedTiming().duration * 2; 94 assert_equals(getComputedStyle(div).color, 'rgb(240, 240, 240)', 95 'Animated color style at 0s of the third iteration'); 96 anim.currentTime += anim.effect.getComputedTiming().duration / 2; 97 assert_equals(getComputedStyle(div).color, 'rgb(255, 255, 255)', 98 'Animated color style at 50s of the third iteration'); 99 }, 'iteration composition of <color> type animation'); 100 101 test(t => { 102 const div = createDiv(t); 103 const anim = 104 div.animate({ color: ['rgb(0, 120, 0)', 'rgb(60, 60, 60)'] }, 105 { duration: 100 * MS_PER_SEC, 106 easing: 'linear', 107 iterations: 10, 108 iterationComposite: 'accumulate' }); 109 anim.pause(); 110 111 anim.currentTime = anim.effect.getComputedTiming().duration / 2; 112 assert_equals(getComputedStyle(div).color, 'rgb(30, 90, 30)', 113 'Animated color style at 50s of the first iteration'); 114 anim.currentTime = anim.effect.getComputedTiming().duration * 2; 115 assert_equals(getComputedStyle(div).color, 'rgb(120, 240, 120)', 116 'Animated color style at 0s of the third iteration'); 117 anim.currentTime += anim.effect.getComputedTiming().duration / 2; 118 // The green color is (240 + 180) / 2 = 210 119 assert_equals(getComputedStyle(div).color, 'rgb(150, 210, 150)', 120 'Animated color style at 50s of the third iteration'); 121 }, 'iteration composition of <color> type animation that green component is ' + 122 'decreasing'); 123 124 test(t => { 125 const div = createDiv(t); 126 const anim = 127 div.animate({ flexGrow: [0, 10] }, 128 { duration: 100 * MS_PER_SEC, 129 easing: 'linear', 130 iterations: 10, 131 iterationComposite: 'accumulate' }); 132 anim.pause(); 133 134 anim.currentTime = anim.effect.getComputedTiming().duration / 2; 135 assert_equals(getComputedStyle(div).flexGrow, '5', 136 'Animated flex-grow style at 50s of the first iteration'); 137 anim.currentTime = anim.effect.getComputedTiming().duration * 2; 138 assert_equals(getComputedStyle(div).flexGrow, '20', 139 'Animated flex-grow style at 0s of the third iteration'); 140 anim.currentTime += anim.effect.getComputedTiming().duration / 2; 141 assert_equals(getComputedStyle(div).flexGrow, '25', 142 'Animated flex-grow style at 50s of the third iteration'); 143 }, 'iteration composition of <number> type animation'); 144 145 test(t => { 146 const div = createDiv(t); 147 div.style.position = 'absolute'; 148 const anim = 149 div.animate({ clip: ['rect(0px, 0px, 0px, 0px)', 150 'rect(10px, 10px, 10px, 10px)'] }, 151 { duration: 100 * MS_PER_SEC, 152 easing: 'linear', 153 iterations: 10, 154 iterationComposite: 'accumulate' }); 155 anim.pause(); 156 157 anim.currentTime = anim.effect.getComputedTiming().duration / 2; 158 assert_equals(getComputedStyle(div).clip, 'rect(5px, 5px, 5px, 5px)', 159 'Animated clip style at 50s of the first iteration'); 160 anim.currentTime = anim.effect.getComputedTiming().duration * 2; 161 assert_equals(getComputedStyle(div).clip, 'rect(20px, 20px, 20px, 20px)', 162 'Animated clip style at 0s of the third iteration'); 163 anim.currentTime += anim.effect.getComputedTiming().duration / 2; 164 assert_equals(getComputedStyle(div).clip, 'rect(25px, 25px, 25px, 25px)', 165 'Animated clip style at 50s of the third iteration'); 166 }, 'iteration composition of <shape> type animation'); 167 168 test(t => { 169 const div = createDiv(t); 170 const anim = 171 div.animate({ width: ['calc(0vw + 0px)', 'calc(0vw + 10px)'] }, 172 { duration: 100 * MS_PER_SEC, 173 easing: 'linear', 174 iterations: 10, 175 iterationComposite: 'accumulate' }); 176 anim.pause(); 177 178 anim.currentTime = anim.effect.getComputedTiming().duration / 2; 179 assert_equals(getComputedStyle(div).width, '5px', 180 'Animated calc width style at 50s of the first iteration'); 181 anim.currentTime = anim.effect.getComputedTiming().duration * 2; 182 assert_equals(getComputedStyle(div).width, '20px', 183 'Animated calc width style at 0s of the third iteration'); 184 anim.currentTime += anim.effect.getComputedTiming().duration / 2; 185 assert_equals(getComputedStyle(div).width, '25px', 186 'Animated calc width style at 50s of the third iteration'); 187 }, 'iteration composition of <calc()> value animation'); 188 189 test(t => { 190 const parent = createDiv(t); 191 parent.style.width = '100px'; 192 const div = createDiv(t); 193 parent.appendChild(div); 194 195 const anim = 196 div.animate({ width: ['calc(0% + 0px)', 'calc(10% + 10px)'] }, 197 { duration: 100 * MS_PER_SEC, 198 easing: 'linear', 199 iterations: 10, 200 iterationComposite: 'accumulate' }); 201 anim.pause(); 202 203 anim.currentTime = anim.effect.getComputedTiming().duration / 2; 204 assert_equals(getComputedStyle(div).width, '10px', 205 // 100px * 5% + 5px 206 'Animated calc width style at 50s of the first iteration'); 207 anim.currentTime = anim.effect.getComputedTiming().duration * 2; 208 assert_equals(getComputedStyle(div).width, 209 '40px', // 100px * (10% + 10%) + (10px + 10px) 210 'Animated calc width style at 0s of the third iteration'); 211 anim.currentTime += anim.effect.getComputedTiming().duration / 2; 212 assert_equals(getComputedStyle(div).width, 213 '50px', // (40px + 60px) / 2 214 'Animated calc width style at 50s of the third iteration'); 215 }, 'iteration composition of <calc()> value animation that the values can\'t' + 216 'be reduced'); 217 218 test(t => { 219 const div = createDiv(t); 220 const anim = 221 div.animate({ opacity: [0, 0.4] }, 222 { duration: 100 * MS_PER_SEC, 223 easing: 'linear', 224 iterations: 10, 225 iterationComposite: 'accumulate' }); 226 anim.pause(); 227 228 anim.currentTime = anim.effect.getComputedTiming().duration / 2; 229 assert_equals(getComputedStyle(div).opacity, '0.2', 230 'Animated opacity style at 50s of the first iteration'); 231 anim.currentTime = anim.effect.getComputedTiming().duration * 2; 232 assert_equals(getComputedStyle(div).opacity, '0.8', 233 'Animated opacity style at 0s of the third iteration'); 234 anim.currentTime += anim.effect.getComputedTiming().duration / 2; 235 assert_equals(getComputedStyle(div).opacity, '1', // (0.8 + 1.2) * 0.5 236 'Animated opacity style at 50s of the third iteration'); 237 }, 'iteration composition of opacity animation'); 238 239 test(t => { 240 const div = createDiv(t); 241 const anim = 242 div.animate({ boxShadow: ['rgb(0, 0, 0) 0px 0px 0px 0px', 243 'rgb(120, 120, 120) 10px 10px 10px 0px'] }, 244 { duration: 100 * MS_PER_SEC, 245 easing: 'linear', 246 iterations: 10, 247 iterationComposite: 'accumulate' }); 248 anim.pause(); 249 250 anim.currentTime = anim.effect.getComputedTiming().duration / 2; 251 assert_equals(getComputedStyle(div).boxShadow, 252 'rgb(60, 60, 60) 5px 5px 5px 0px', 253 'Animated box-shadow style at 50s of the first iteration'); 254 anim.currentTime = anim.effect.getComputedTiming().duration * 2; 255 assert_equals(getComputedStyle(div).boxShadow, 256 'rgb(240, 240, 240) 20px 20px 20px 0px', 257 'Animated box-shadow style at 0s of the third iteration'); 258 anim.currentTime += anim.effect.getComputedTiming().duration / 2; 259 assert_equals(getComputedStyle(div).boxShadow, 260 'rgb(255, 255, 255) 25px 25px 25px 0px', 261 'Animated box-shadow style at 50s of the third iteration'); 262 }, 'iteration composition of box-shadow animation'); 263 264 test(t => { 265 const div = createDiv(t); 266 const anim = 267 div.animate({ filter: ['blur(0px)', 'blur(10px)'] }, 268 { duration: 100 * MS_PER_SEC, 269 easing: 'linear', 270 iterations: 10, 271 iterationComposite: 'accumulate' }); 272 anim.pause(); 273 274 anim.currentTime = anim.effect.getComputedTiming().duration / 2; 275 assert_equals(getComputedStyle(div).filter, 'blur(5px)', 276 'Animated filter blur style at 50s of the first iteration'); 277 anim.currentTime = anim.effect.getComputedTiming().duration * 2; 278 assert_equals(getComputedStyle(div).filter, 'blur(20px)', 279 'Animated filter blur style at 0s of the third iteration'); 280 anim.currentTime += anim.effect.getComputedTiming().duration / 2; 281 assert_equals(getComputedStyle(div).filter, 'blur(25px)', 282 'Animated filter blur style at 50s of the third iteration'); 283 }, 'iteration composition of filter blur animation'); 284 285 test(t => { 286 const div = createDiv(t); 287 const anim = 288 div.animate({ filter: ['brightness(1)', 289 'brightness(180%)'] }, 290 { duration: 100 * MS_PER_SEC, 291 easing: 'linear', 292 iterations: 10, 293 iterationComposite: 'accumulate' }); 294 anim.pause(); 295 296 anim.currentTime = anim.effect.getComputedTiming().duration / 2; 297 assert_equals(getComputedStyle(div).filter, 298 'brightness(1.4)', 299 'Animated filter brightness style at 50s of the first iteration'); 300 anim.currentTime = anim.effect.getComputedTiming().duration * 2; 301 assert_equals(getComputedStyle(div).filter, 302 'brightness(2.6)', // brightness(1) + brightness(0.8) + brightness(0.8) 303 'Animated filter brightness style at 0s of the third iteration'); 304 anim.currentTime += anim.effect.getComputedTiming().duration / 2; 305 assert_equals(getComputedStyle(div).filter, 306 'brightness(3)', // (brightness(2.6) + brightness(3.4)) * 0.5 307 'Animated filter brightness style at 50s of the third iteration'); 308 }, 'iteration composition of filter brightness for different unit animation'); 309 310 test(t => { 311 const div = createDiv(t); 312 const anim = 313 div.animate({ filter: ['brightness(0)', 314 'brightness(1)'] }, 315 { duration: 100 * MS_PER_SEC, 316 easing: 'linear', 317 iterations: 10, 318 iterationComposite: 'accumulate' }); 319 anim.pause(); 320 321 anim.currentTime = anim.effect.getComputedTiming().duration / 2; 322 assert_equals(getComputedStyle(div).filter, 323 'brightness(0.5)', 324 'Animated filter brightness style at 50s of the first iteration'); 325 anim.currentTime = anim.effect.getComputedTiming().duration * 2; 326 assert_equals(getComputedStyle(div).filter, 327 'brightness(0)', // brightness(1) is an identity element, not accumulated. 328 'Animated filter brightness style at 0s of the third iteration'); 329 anim.currentTime += anim.effect.getComputedTiming().duration / 2; 330 assert_equals(getComputedStyle(div).filter, 331 'brightness(0.5)', // brightness(1) is an identity element, not accumulated. 332 'Animated filter brightness style at 50s of the third iteration'); 333 }, 'iteration composition of filter brightness animation'); 334 335 test(t => { 336 const div = createDiv(t); 337 const anim = 338 div.animate({ filter: ['drop-shadow(rgb(0, 0, 0) 0px 0px 0px)', 339 'drop-shadow(rgb(120, 120, 120) 10px 10px 10px)'] }, 340 { duration: 100 * MS_PER_SEC, 341 easing: 'linear', 342 iterations: 10, 343 iterationComposite: 'accumulate' }); 344 anim.pause(); 345 346 anim.currentTime = anim.effect.getComputedTiming().duration / 2; 347 assert_equals(getComputedStyle(div).filter, 348 'drop-shadow(rgb(60, 60, 60) 5px 5px 5px)', 349 'Animated filter drop-shadow style at 50s of the first iteration'); 350 anim.currentTime = anim.effect.getComputedTiming().duration * 2; 351 assert_equals(getComputedStyle(div).filter, 352 'drop-shadow(rgb(240, 240, 240) 20px 20px 20px)', 353 'Animated filter drop-shadow style at 0s of the third iteration'); 354 anim.currentTime += anim.effect.getComputedTiming().duration / 2; 355 assert_equals(getComputedStyle(div).filter, 356 'drop-shadow(rgb(255, 255, 255) 25px 25px 25px)', 357 'Animated filter drop-shadow style at 50s of the third iteration'); 358 }, 'iteration composition of filter drop-shadow animation'); 359 360 test(t => { 361 const div = createDiv(t); 362 const anim = 363 div.animate({ filter: ['brightness(1) contrast(1)', 364 'brightness(2) contrast(2)'] }, 365 { duration: 100 * MS_PER_SEC, 366 easing: 'linear', 367 iterations: 10, 368 iterationComposite: 'accumulate' }); 369 anim.pause(); 370 371 anim.currentTime = anim.effect.getComputedTiming().duration / 2; 372 assert_equals(getComputedStyle(div).filter, 373 'brightness(1.5) contrast(1.5)', 374 'Animated filter list at 50s of the first iteration'); 375 anim.currentTime = anim.effect.getComputedTiming().duration * 2; 376 assert_equals(getComputedStyle(div).filter, 377 'brightness(3) contrast(3)', 378 'Animated filter list at 0s of the third iteration'); 379 anim.currentTime += anim.effect.getComputedTiming().duration / 2; 380 assert_equals(getComputedStyle(div).filter, 381 'brightness(3.5) contrast(3.5)', 382 'Animated filter list at 50s of the third iteration'); 383 }, 'iteration composition of same filter list animation'); 384 385 test(t => { 386 const div = createDiv(t); 387 const anim = 388 div.animate({ filter: ['brightness(1) contrast(1)', 389 'contrast(2) brightness(2)'] }, 390 { duration: 100 * MS_PER_SEC, 391 easing: 'linear', 392 iterations: 10, 393 iterationComposite: 'accumulate' }); 394 anim.pause(); 395 396 anim.currentTime = anim.effect.getComputedTiming().duration / 2; 397 assert_equals(getComputedStyle(div).filter, 398 'contrast(2) brightness(2)', // discrete 399 'Animated filter list at 50s of the first iteration'); 400 anim.currentTime = anim.effect.getComputedTiming().duration * 2; 401 assert_equals(getComputedStyle(div).filter, 402 // We can't accumulate 'contrast(2) brightness(2)' onto 403 // the first list 'brightness(1) contrast(1)' because of 404 // mismatch of the order. 405 'brightness(1) contrast(1)', 406 'Animated filter list at 0s of the third iteration'); 407 anim.currentTime += anim.effect.getComputedTiming().duration / 2; 408 assert_equals(getComputedStyle(div).filter, 409 // We *can* accumulate 'contrast(2) brightness(2)' onto 410 // the same list 'contrast(2) brightness(2)' here. 411 'contrast(4) brightness(4)', // discrete 412 'Animated filter list at 50s of the third iteration'); 413 }, 'iteration composition of discrete filter list because of mismatch ' + 414 'of the order'); 415 416 test(t => { 417 const div = createDiv(t); 418 const anim = 419 div.animate({ filter: ['sepia(0)', 420 'sepia(1) contrast(2)'] }, 421 { duration: 100 * MS_PER_SEC, 422 easing: 'linear', 423 iterations: 10, 424 iterationComposite: 'accumulate' }); 425 anim.pause(); 426 427 anim.currentTime = anim.effect.getComputedTiming().duration / 2; 428 assert_equals(getComputedStyle(div).filter, 429 'sepia(0.5) contrast(1.5)', 430 'Animated filter list at 50s of the first iteration'); 431 anim.currentTime = anim.effect.getComputedTiming().duration * 2; 432 assert_equals(getComputedStyle(div).filter, 433 'sepia(1) contrast(3)', 434 'Animated filter list at 0s of the third iteration'); 435 anim.currentTime += anim.effect.getComputedTiming().duration / 2; 436 assert_equals(getComputedStyle(div).filter, 437 'sepia(1) contrast(3.5)', 438 'Animated filter list at 50s of the third iteration'); 439 }, 'iteration composition of different length filter list animation'); 440 441 test(t => { 442 const div = createDiv(t); 443 const anim = 444 div.animate({ transform: ['rotate(0deg)', 'rotate(180deg)'] }, 445 { duration: 100 * MS_PER_SEC, 446 easing: 'linear', 447 iterations: 10, 448 iterationComposite: 'accumulate' }); 449 anim.pause(); 450 451 anim.currentTime = anim.effect.getComputedTiming().duration / 2; 452 assert_matrix_equals(getComputedStyle(div).transform, 453 'matrix(0, 1, -1, 0, 0, 0)', // rotate(90deg) 454 'Animated transform(rotate) style at 50s of the first iteration'); 455 anim.currentTime = anim.effect.getComputedTiming().duration * 2; 456 assert_matrix_equals(getComputedStyle(div).transform, 457 'matrix(1, 0, 0, 1, 0, 0)', // rotate(360deg) 458 'Animated transform(rotate) style at 0s of the third iteration'); 459 anim.currentTime += anim.effect.getComputedTiming().duration / 2; 460 assert_matrix_equals(getComputedStyle(div).transform, 461 'matrix(0, 1, -1, 0, 0, 0)', // rotate(450deg) 462 'Animated transform(rotate) style at 50s of the third iteration'); 463 }, 'iteration composition of transform(rotate) animation'); 464 465 test(t => { 466 const div = createDiv(t); 467 const anim = 468 div.animate({ transform: ['scale(0)', 'scale(1)'] }, 469 { duration: 100 * MS_PER_SEC, 470 easing: 'linear', 471 iterations: 10, 472 iterationComposite: 'accumulate' }); 473 anim.pause(); 474 475 anim.currentTime = anim.effect.getComputedTiming().duration / 2; 476 assert_matrix_equals(getComputedStyle(div).transform, 477 'matrix(0.5, 0, 0, 0.5, 0, 0)', // scale(0.5) 478 'Animated transform(scale) style at 50s of the first iteration'); 479 anim.currentTime = anim.effect.getComputedTiming().duration * 2; 480 assert_matrix_equals(getComputedStyle(div).transform, 481 'matrix(0, 0, 0, 0, 0, 0)', // scale(0); scale(1) is an identity element, 482 // not accumulated. 483 'Animated transform(scale) style at 0s of the third iteration'); 484 anim.currentTime += anim.effect.getComputedTiming().duration / 2; 485 assert_matrix_equals(getComputedStyle(div).transform, 486 'matrix(0.5, 0, 0, 0.5, 0, 0)', // scale(0.5); scale(1) an identity 487 // element, not accumulated. 488 'Animated transform(scale) style at 50s of the third iteration'); 489 }, 'iteration composition of transform: [ scale(0), scale(1) ] animation'); 490 491 test(t => { 492 const div = createDiv(t); 493 const anim = 494 div.animate({ transform: ['scale(1)', 'scale(2)'] }, 495 { duration: 100 * MS_PER_SEC, 496 easing: 'linear', 497 iterations: 10, 498 iterationComposite: 'accumulate' }); 499 anim.pause(); 500 501 anim.currentTime = anim.effect.getComputedTiming().duration / 2; 502 assert_matrix_equals(getComputedStyle(div).transform, 503 'matrix(1.5, 0, 0, 1.5, 0, 0)', // scale(1.5) 504 'Animated transform(scale) style at 50s of the first iteration'); 505 anim.currentTime = anim.effect.getComputedTiming().duration * 2; 506 assert_matrix_equals(getComputedStyle(div).transform, 507 'matrix(3, 0, 0, 3, 0, 0)', // scale(1 + (2 -1) + (2 -1)) 508 'Animated transform(scale) style at 0s of the third iteration'); 509 anim.currentTime += anim.effect.getComputedTiming().duration / 2; 510 assert_matrix_equals(getComputedStyle(div).transform, 511 'matrix(3.5, 0, 0, 3.5, 0, 0)', // (scale(3) + scale(4)) * 0.5 512 'Animated transform(scale) style at 50s of the third iteration'); 513 }, 'iteration composition of transform: [ scale(1), scale(2) ] animation'); 514 515 test(t => { 516 const div = createDiv(t); 517 const anim = 518 div.animate({ transform: ['scale(0)', 'scale(2)'] }, 519 { duration: 100 * MS_PER_SEC, 520 easing: 'linear', 521 iterations: 10, 522 iterationComposite: 'accumulate' }); 523 anim.pause(); 524 525 anim.currentTime = anim.effect.getComputedTiming().duration / 2; 526 assert_matrix_equals(getComputedStyle(div).transform, 527 'matrix(1, 0, 0, 1, 0, 0)', // scale(1) 528 'Animated transform(scale) style at 50s of the first iteration'); 529 anim.currentTime = anim.effect.getComputedTiming().duration * 2; 530 assert_matrix_equals(getComputedStyle(div).transform, 531 'matrix(2, 0, 0, 2, 0, 0)', // (scale(0) + scale(2-1)*2) 532 'Animated transform(scale) style at 0s of the third iteration'); 533 anim.currentTime += anim.effect.getComputedTiming().duration / 2; 534 assert_matrix_equals(getComputedStyle(div).transform, 535 'matrix(3, 0, 0, 3, 0, 0)', // (scale(2) + scale(4)) * 0.5 536 'Animated transform(scale) style at 50s of the third iteration'); 537 }, 'iteration composition of transform: scale(2) animation'); 538 539 test(t => { 540 const div = createDiv(t); 541 const anim = 542 div.animate({ transform: ['rotate(0deg) translateX(0px)', 543 'rotate(180deg) translateX(10px)'] }, 544 { duration: 100 * MS_PER_SEC, 545 easing: 'linear', 546 iterations: 10, 547 iterationComposite: 'accumulate' }); 548 anim.pause(); 549 550 anim.currentTime = anim.effect.getComputedTiming().duration / 2; 551 assert_matrix_equals(getComputedStyle(div).transform, 552 'matrix(0, 1, -1, 0, 0, 5)', // rotate(90deg) translateX(5px) 553 'Animated transform list at 50s of the first iteration'); 554 anim.currentTime = anim.effect.getComputedTiming().duration * 2; 555 assert_matrix_equals(getComputedStyle(div).transform, 556 'matrix(1, 0, 0, 1, 20, 0)', // rotate(360deg) translateX(20px) 557 'Animated transform list at 0s of the third iteration'); 558 anim.currentTime += anim.effect.getComputedTiming().duration / 2; 559 assert_matrix_equals(getComputedStyle(div).transform, 560 'matrix(0, 1, -1, 0, 0, 25)', // rotate(450deg) translateX(25px) 561 'Animated transform list at 50s of the third iteration'); 562 }, 'iteration composition of transform list animation'); 563 564 test(t => { 565 const div = createDiv(t); 566 const anim = 567 div.animate({ transform: ['matrix(2, 0, 0, 2, 0, 0)', 568 'matrix(3, 0, 0, 3, 30, 0)'] }, 569 { duration: 100 * MS_PER_SEC, 570 easing: 'linear', 571 iterations: 10, 572 iterationComposite: 'accumulate' }); 573 anim.pause(); 574 575 anim.currentTime = anim.effect.getComputedTiming().duration / 2; 576 assert_matrix_equals(getComputedStyle(div).transform, 577 'matrix(2.5, 0, 0, 2.5, 15, 0)', 578 'Animated transform of matrix function at 50s of the first iteration'); 579 anim.currentTime = anim.effect.getComputedTiming().duration * 2; 580 assert_matrix_equals(getComputedStyle(div).transform, 581 // scale(2) + (scale(3-1)*2) + translateX(30px)*2 582 'matrix(6, 0, 0, 6, 60, 0)', 583 'Animated transform of matrix function at 0s of the third iteration'); 584 anim.currentTime += anim.effect.getComputedTiming().duration / 2; 585 assert_matrix_equals(getComputedStyle(div).transform, 586 // from: matrix(6, 0, 0, 6, 60, 0) 587 // to: matrix(7, 0, 0, 7, 90, 0) 588 // = scale(3) + (scale(3-1)*2) + translateX(30px)*3 589 'matrix(6.5, 0, 0, 6.5, 75, 0)', 590 'Animated transform of matrix function at 50s of the third iteration'); 591 }, 'iteration composition of transform of matrix function'); 592 593 test(t => { 594 const div = createDiv(t); 595 const anim = 596 div.animate({ transform: ['translateX(0px) scale(2)', 597 'scale(3) translateX(10px)'] }, 598 { duration: 100 * MS_PER_SEC, 599 easing: 'linear', 600 iterations: 10, 601 iterationComposite: 'accumulate' }); 602 anim.pause(); 603 604 anim.currentTime = anim.effect.getComputedTiming().duration / 2; 605 assert_matrix_equals(getComputedStyle(div).transform, 606 // Interpolate between matrix(2, 0, 0, 2, 0, 0) = translateX(0px) scale(2) 607 // and matrix(3, 0, 0, 3, 30, 0) = scale(3) translateX(10px) 608 'matrix(2.5, 0, 0, 2.5, 15, 0)', 609 'Animated transform list at 50s of the first iteration'); 610 anim.currentTime = anim.effect.getComputedTiming().duration * 2; 611 assert_matrix_equals(getComputedStyle(div).transform, 612 // 'from' and 'to' value are mismatched, so accumulate 613 // matrix(2, 0, 0, 2, 0, 0) onto matrix(3, 0, 0, 3, 30, 0) * 2 614 // = scale(2) + (scale(3-1)*2) + translateX(30px)*2 615 'matrix(6, 0, 0, 6, 60, 0)', 616 'Animated transform list at 0s of the third iteration'); 617 anim.currentTime += anim.effect.getComputedTiming().duration / 2; 618 assert_matrix_equals(getComputedStyle(div).transform, 619 // Interpolate between matrix(6, 0, 0, 6, 60, 0) 620 // and matrix(7, 0, 0, 7, 210, 0) = scale(7) translate(30px) 621 'matrix(6.5, 0, 0, 6.5, 135, 0)', 622 'Animated transform list at 50s of the third iteration'); 623 }, 'iteration composition of transform list animation whose order is' 624 + ' mismatched'); 625 626 test(t => { 627 const div = createDiv(t); 628 // Even if each transform list does not have functions which exist in 629 // other pair of the list, we don't fill any missing functions at all. 630 const anim = 631 div.animate({ transform: ['translateX(0px)', 632 'scale(2) translateX(10px)'] }, 633 { duration: 100 * MS_PER_SEC, 634 easing: 'linear', 635 iterations: 10, 636 iterationComposite: 'accumulate' }); 637 anim.pause(); 638 639 anim.currentTime = anim.effect.getComputedTiming().duration / 2; 640 assert_matrix_equals(getComputedStyle(div).transform, 641 // Interpolate between matrix(1, 0, 0, 1, 0, 0) = translateX(0px) 642 // and matrix(2, 0, 0, 2, 20, 0) = scale(2) translateX(10px) 643 'matrix(1.5, 0, 0, 1.5, 10, 0)', 644 'Animated transform list at 50s of the first iteration'); 645 anim.currentTime = anim.effect.getComputedTiming().duration * 2; 646 assert_matrix_equals(getComputedStyle(div).transform, 647 // 'from' and 'to' value are mismatched, so accumulate 648 // matrix(1, 0, 0, 1, 0, 0) onto matrix(2, 0, 0, 2, 20, 0) * 2 649 // = scale(1) + (scale(2-1)*2) + translateX(20px)*2 650 'matrix(3, 0, 0, 3, 40, 0)', 651 'Animated transform list at 0s of the third iteration'); 652 anim.currentTime += anim.effect.getComputedTiming().duration / 2; 653 assert_matrix_equals(getComputedStyle(div).transform, 654 // Interpolate between matrix(3, 0, 0, 3, 40, 0) 655 // and matrix(4, 0, 0, 4, 120, 0) = 656 // scale(2 + (2-1)*2) translate(10px * 3) 657 'matrix(3.5, 0, 0, 3.5, 80, 0)', 658 'Animated transform list at 50s of the third iteration'); 659 }, 'iteration composition of transform list animation whose order is' 660 + ' mismatched because of missing functions'); 661 662 test(t => { 663 const div = createDiv(t); 664 const anim = 665 div.animate({ transform: ['none', 666 'translateX(10px)'] }, 667 { duration: 100 * MS_PER_SEC, 668 easing: 'linear', 669 iterations: 10, 670 iterationComposite: 'accumulate' }); 671 anim.pause(); 672 673 anim.currentTime = anim.effect.getComputedTiming().duration / 2; 674 assert_matrix_equals(getComputedStyle(div).transform, 675 // translateX(none) -> translateX(10px) @ 50% 676 'matrix(1, 0, 0, 1, 5, 0)', 677 'Animated transform list at 50s of the first iteration'); 678 anim.currentTime = anim.effect.getComputedTiming().duration * 2; 679 assert_matrix_equals(getComputedStyle(div).transform, 680 // translateX(10px * 2 + none) -> translateX(10px * 2 + 10px) @ 0% 681 'matrix(1, 0, 0, 1, 20, 0)', 682 'Animated transform list at 0s of the third iteration'); 683 anim.currentTime += anim.effect.getComputedTiming().duration / 2; 684 assert_matrix_equals(getComputedStyle(div).transform, 685 // translateX(10px * 2 + none) -> translateX(10px * 2 + 10px) @ 50% 686 'matrix(1, 0, 0, 1, 25, 0)', 687 'Animated transform list at 50s of the third iteration'); 688 }, 'iteration composition of transform from none to translate'); 689 690 test(t => { 691 const div = createDiv(t); 692 const anim = 693 div.animate({ transform: ['matrix3d(1, 0, 0, 0, ' + 694 '0, 1, 0, 0, ' + 695 '0, 0, 1, 0, ' + 696 '0, 0, 30, 1)', 697 'matrix3d(1, 0, 0, 0, ' + 698 '0, 1, 0, 0, ' + 699 '0, 0, 1, 0, ' + 700 '0, 0, 50, 1)'] }, 701 { duration: 100 * MS_PER_SEC, 702 easing: 'linear', 703 iterations: 10, 704 iterationComposite: 'accumulate' }); 705 anim.pause(); 706 707 anim.currentTime = anim.effect.getComputedTiming().duration / 2; 708 assert_matrix_equals(getComputedStyle(div).transform, 709 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 40, 1)', 710 'Animated transform of matrix3d function at 50s of the first iteration'); 711 anim.currentTime = anim.effect.getComputedTiming().duration * 2; 712 assert_matrix_equals(getComputedStyle(div).transform, 713 // translateZ(30px) + (translateZ(50px)*2) 714 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 130, 1)', 715 'Animated transform of matrix3d function at 0s of the third iteration'); 716 anim.currentTime += anim.effect.getComputedTiming().duration / 2; 717 assert_matrix_equals(getComputedStyle(div).transform, 718 // from: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 130, 1) 719 // to: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 150, 1) 720 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 140, 1)', 721 'Animated transform of matrix3d function at 50s of the third iteration'); 722 }, 'iteration composition of transform of matrix3d function'); 723 724 test(t => { 725 const div = createDiv(t); 726 const anim = 727 div.animate({ transform: ['rotate3d(1, 1, 0, 0deg)', 728 'rotate3d(1, 1, 0, 90deg)'] }, 729 { duration: 100 * MS_PER_SEC, 730 easing: 'linear', 731 iterations: 10, 732 iterationComposite: 'accumulate' }); 733 anim.pause(); 734 735 anim.currentTime = 0; 736 assert_matrix_equals(getComputedStyle(div).transform, 737 'matrix(1, 0, 0, 1, 0, 0)', // Actually not rotated at all. 738 'Animated transform of rotate3d function at 50s of the first iteration'); 739 anim.currentTime = anim.effect.getComputedTiming().duration * 2; 740 assert_matrix_equals(getComputedStyle(div).transform, 741 rotate3dToMatrix3d(1, 1, 0, Math.PI), // 180deg 742 'Animated transform of rotate3d function at 0s of the third iteration'); 743 anim.currentTime += anim.effect.getComputedTiming().duration / 2; 744 assert_matrix_equals(getComputedStyle(div).transform, 745 rotate3dToMatrix3d(1, 1, 0, 225 * Math.PI / 180), //((270 + 180) * 0.5)deg 746 'Animated transform of rotate3d function at 50s of the third iteration'); 747 }, 'iteration composition of transform of rotate3d function'); 748 749 test(t => { 750 const div = createDiv(t); 751 const anim = 752 div.animate({ marginLeft: ['10px', '20px'] }, 753 { duration: 100 * MS_PER_SEC, 754 easing: 'linear', 755 iterations: 10, 756 iterationComposite: 'accumulate' }); 757 anim.pause(); 758 759 anim.currentTime = anim.effect.getComputedTiming().duration / 2; 760 assert_equals(getComputedStyle(div).marginLeft, '15px', 761 'Animated margin-left style at 50s of the first iteration'); 762 anim.currentTime = anim.effect.getComputedTiming().duration * 2; 763 assert_equals(getComputedStyle(div).marginLeft, '50px', // 10px + 20px + 20px 764 'Animated margin-left style at 0s of the third iteration'); 765 anim.currentTime += anim.effect.getComputedTiming().duration / 2; 766 assert_equals(getComputedStyle(div).marginLeft, '55px', // (50px + 60px) * 0.5 767 'Animated margin-left style at 50s of the third iteration'); 768 }, 'iteration composition starts with non-zero value animation'); 769 770 test(t => { 771 const div = createDiv(t); 772 const anim = 773 div.animate({ marginLeft: ['10px', '-10px'] }, 774 { duration: 100 * MS_PER_SEC, 775 easing: 'linear', 776 iterations: 10, 777 iterationComposite: 'accumulate' }); 778 anim.pause(); 779 780 anim.currentTime = anim.effect.getComputedTiming().duration / 2; 781 assert_equals(getComputedStyle(div).marginLeft, 782 '0px', 783 'Animated margin-left style at 50s of the first iteration'); 784 anim.currentTime = anim.effect.getComputedTiming().duration * 2; 785 assert_equals(getComputedStyle(div).marginLeft, 786 '-10px', // 10px + -10px + -10px 787 'Animated margin-left style at 0s of the third iteration'); 788 anim.currentTime += anim.effect.getComputedTiming().duration / 2; 789 assert_equals(getComputedStyle(div).marginLeft, 790 '-20px', // (-10px + -30px) * 0.5 791 'Animated margin-left style at 50s of the third iteration'); 792 }, 'iteration composition with negative final value animation'); 793 794 test(t => { 795 const div = createDiv(t); 796 const anim = div.animate({ marginLeft: ['0px', '10px'] }, 797 { duration: 100 * MS_PER_SEC, 798 easing: 'linear', 799 iterations: 10, 800 iterationComposite: 'accumulate' }); 801 anim.pause(); 802 803 anim.currentTime = 804 anim.effect.getComputedTiming().duration * 2 + 805 anim.effect.getComputedTiming().duration / 2; 806 assert_equals(getComputedStyle(div).marginLeft, '25px', 807 'Animated style at 50s of the third iteration'); 808 809 // double its duration. 810 anim.effect.updateTiming({ 811 duration: anim.effect.getComputedTiming().duration * 2 812 }); 813 assert_equals(getComputedStyle(div).marginLeft, '12.5px', 814 'Animated style at 25s of the first iteration'); 815 816 // half of original. 817 anim.effect.updateTiming({ 818 duration: anim.effect.getComputedTiming().duration / 4 819 }); 820 assert_equals(getComputedStyle(div).marginLeft, '50px', 821 'Animated style at 50s of the fourth iteration'); 822 }, 'duration changes with an iteration composition operation of accumulate'); 823 824 </script>