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