effect-composition.html (5387B)
1 <!doctype html> 2 <meta charset=utf-8> 3 <title>Effect composition</title> 4 <link rel="help" href="https://drafts.csswg.org/web-animations/#effect-composition"> 5 <script src=/resources/testharness.js></script> 6 <script src=/resources/testharnessreport.js></script> 7 <script src="../../testcommon.js"></script> 8 <div id="log"></div> 9 <script> 10 'use strict'; 11 12 for (const composite of ['accumulate', 'add']) { 13 test(t => { 14 const div = createDiv(t); 15 div.style.marginLeft = '10px'; 16 const anim = 17 div.animate({ marginLeft: ['0px', '10px'], composite }, 100); 18 19 anim.currentTime = 50; 20 assert_equals(getComputedStyle(div).marginLeft, '15px', 21 'Animated margin-left style at 50%'); 22 }, `${composite} onto the base value`); 23 24 test(t => { 25 const div = createDiv(t); 26 div.style.marginLeft = '10px'; 27 const anim = 28 div.animate([{ marginLeft: '20px', offset: 0.25 }, { marginLeft: '30px', offset: 0.75 }], 29 { duration: 100, composite }); 30 31 anim.currentTime = 50; 32 assert_equals(getComputedStyle(div).marginLeft, '35px', 33 'Animated margin-left style at 50%'); 34 }, `${composite} onto the base value when the interval does not include the 0 or 1 keyframe`); 35 36 test(t => { 37 const div = createDiv(t); 38 const anims = []; 39 anims.push(div.animate({ marginLeft: ['10px', '20px'], 40 composite: 'replace' }, 41 100)); 42 anims.push(div.animate({ marginLeft: ['0px', '10px'], 43 composite }, 44 100)); 45 46 for (const anim of anims) { 47 anim.currentTime = 50; 48 } 49 50 assert_equals(getComputedStyle(div).marginLeft, '20px', 51 'Animated style at 50%'); 52 }, `${composite} onto an underlying animation value`); 53 54 test(t => { 55 const div = createDiv(t); 56 const anims = []; 57 anims.push(div.animate({ transform: 'translateX(100px)' }, { duration: 100, composite: 'replace' })); 58 anims.push(div.animate({ transform: 'translateY(100px)' }, { duration: 100, composite })); 59 60 for (const anim of anims) { 61 anim.currentTime = 50; 62 } 63 64 assert_equals(getComputedStyle(div).transform, 'matrix(1, 0, 0, 1, 50, 50)', 65 'Animated style at 50%'); 66 }, `${composite} onto an underlying animation value with implicit from values`); 67 68 test(t => { 69 const div = createDiv(t); 70 const anims = []; 71 anims.push(div.animate([{ offset: 1, transform: 'translateX(100px)' }], { duration: 100, composite: 'replace' })); 72 anims.push(div.animate([{ offset: 1, transform: 'translateY(100px)' }], { duration: 100, composite })); 73 74 for (const anim of anims) { 75 anim.currentTime = 50; 76 } 77 78 assert_equals(getComputedStyle(div).transform, 'matrix(1, 0, 0, 1, 50, 50)', 79 'Animated style at 50%'); 80 }, `${composite} onto an underlying animation value with implicit to values`); 81 82 test(t => { 83 const div = createDiv(t); 84 div.style.marginLeft = '10px'; 85 const anim = 86 div.animate([{ marginLeft: '10px', composite }, 87 { marginLeft: '30px', composite: 'replace' }], 88 100); 89 90 anim.currentTime = 50; 91 assert_equals(getComputedStyle(div).marginLeft, '25px', 92 'Animated style at 50%'); 93 }, `Composite when mixing ${composite} and replace`); 94 95 test(t => { 96 const div = createDiv(t); 97 div.style.marginLeft = '10px'; 98 const anim = 99 div.animate([{ marginLeft: '10px', composite: 'replace' }, 100 { marginLeft: '20px' }], 101 { duration: 100 , composite }); 102 103 anim.currentTime = 50; 104 assert_equals(getComputedStyle(div).marginLeft, '20px', 105 'Animated style at 50%'); 106 }, `${composite} specified on a keyframe overrides the composite mode of` 107 + ' the effect'); 108 109 test(t => { 110 const div = createDiv(t); 111 div.style.marginLeft = '10px'; 112 const anim = 113 div.animate([{ marginLeft: '10px', composite: 'replace' }, 114 { marginLeft: '20px' }], 115 100); 116 117 anim.effect.composite = composite; 118 anim.currentTime = 50; // (10 + (10 + 20)) * 0.5 119 assert_equals(getComputedStyle(div).marginLeft, '20px', 120 'Animated style at 50%'); 121 }, 'unspecified composite mode on a keyframe is overriden by setting' 122 + ` ${composite} of the effect`); 123 } 124 125 test(t => { 126 const div = createDiv(t); 127 const anims = []; 128 anims.push(div.animate({ marginLeft: ['10px', '20px'], 129 composite: 'replace' }, 130 100)); 131 anims.push(div.animate({ marginLeft: ['0px', '10px'], 132 composite: 'add' }, 133 100)); 134 // This should fully replace the previous effects. 135 anims.push(div.animate({ marginLeft: ['20px', '30px'], 136 composite: 'replace' }, 137 100)); 138 anims.push(div.animate({ marginLeft: ['30px', '40px'], 139 composite: 'add' }, 140 100)); 141 142 for (const anim of anims) { 143 anim.currentTime = 50; 144 } 145 146 // The result of applying the above effect stack is: 147 // underlying = 0.5 * 20 + 0.5 * 30 = 25 148 // result = 0.5 * (underlying + 30px) + 0.5 * (underlying + 40px) 149 // = 60 150 assert_equals(getComputedStyle(div).marginLeft, '60px', 151 'Animated style at 50%'); 152 }, 'Composite replace fully replaces the underlying animation value'); 153 154 </script>