mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-11-12 06:08:24 +02:00
Automatic update from web-platform-tests
Fix bug where composite: replace did not replace previous effects
Consider a set of effects:
e.animate([{ "width": "0" }, { "width": "5px" }], { duration: 100 });
e.animate([{ "width": "0" }, { "width": "5px" }], { duration: 100, composite: 'add' });
e.animate([{ "width": "0" }, { "width": "2px" }], { duration: 100 });
e.animate([{ "width": "0" }, { "width": "2px" }], { duration: 100, composite: 'add' });
Previously the code in CopyToActiveInterpolationsMap would incorrectly
move the third effect to the start of the list to replace the original
keyframe pair, resulting in an effect stack of:
{ "width": "0" }, { "width": "2px" }
{ "width": "0" }, { "width": "5px" }
{ "width": "0" }, { "width": "2px" }
This is wrong; not only has it retained an effect it shouldn't have, it
has also re-ordered keyframes which might break non-commutative additive
properties. This CL fixes the logic to properly clear out existing
effects when a composite: 'replace' effect is put onto the stack.
Bug: 992378
Change-Id: I94ae54429ac7d4d28a0702d397ab64c2e45dee65
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1746302
Commit-Queue: Stephen McGruer <smcgruer@chromium.org>
Reviewed-by: Yi Gu <yigu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#686024}
--
wpt-commits: a851a6a8e8b11160bcd6f5861553cf8419258136
wpt-pr: 18356
114 lines
3.7 KiB
HTML
114 lines
3.7 KiB
HTML
<!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);
|
|
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);
|
|
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>
|