Source code
Revision control
Copy as Markdown
Other Tools
Test Info:
- This WPT test may be referenced by the following Test IDs:
- /web-animations/timing-model/time-transformations/transformed-progress.html - WPT Dashboard Interop Dashboard
<!DOCTYPE html>
<meta charset=utf-8>
<title>Transformed progress</title>
<link rel="help" href="https://drafts.csswg.org/web-animations/#calculating-the-transformed-progress">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
<script src="../../resources/easing-tests.js"></script>
<body>
<div id="log"></div>
<div id="target"></div>
<script>
'use strict';
for (const params of gEasingTests) {
test(t => {
const target = createDiv(t);
const anim = target.animate(null, { duration: 1000,
fill: 'forwards',
easing: params.easing });
for (const sampleTime of [0, 250, 500, 750, 1000]) {
anim.currentTime = sampleTime;
const portion = sampleTime / anim.effect.getComputedTiming().duration;
const expectedProgress = params.easingFunction(portion);
assert_approx_equals(anim.effect.getComputedTiming().progress,
expectedProgress,
0.01,
'The progress should be approximately ' +
`${expectedProgress} at ${sampleTime}ms`);
}
}, `Transformed progress for ${params.desc}`);
}
// Additional tests for various boundary conditions of step timing functions.
const gStepTimingFunctionTests = [
{
description: 'Test bounds point of step-start easing',
effect: {
delay: 1000,
duration: 1000,
fill: 'both',
easing: 'steps(2, start)'
},
conditions: [
{ currentTime: 0, progress: 0 },
{ currentTime: 999, progress: 0 },
{ currentTime: 1000, progress: 0.5 },
{ currentTime: 1499, progress: 0.5 },
{ currentTime: 1500, progress: 1 },
{ currentTime: 2000, progress: 1 }
]
},
{
description: 'Test start bounds of step-start easing with no delay',
effect: {
delay: 0,
duration: 1000,
fill: 'backwards',
easing: 'steps(1, start)'
},
conditions: [
{ currentTime: -1, progress: 0 },
{ currentTime: 0, progress: 1 }
]
},
{
description: 'Test bounds point of step-start easing with reverse direction',
effect: {
delay: 1000,
duration: 1000,
fill: 'both',
direction: 'reverse',
easing: 'steps(2, start)'
},
conditions: [
{ currentTime: 0, progress: 1 },
{ currentTime: 1001, progress: 1 },
{ currentTime: 1500, progress: 1 },
{ currentTime: 1501, progress: 0.5 },
{ currentTime: 2000, progress: 0 },
{ currentTime: 2500, progress: 0 }
]
},
{
description: 'Test bounds point of step-start easing ' +
'with iterationStart not at a transition point',
effect: {
delay: 1000,
duration: 1000,
fill: 'both',
iterationStart: 0.25,
easing: 'steps(2, start)'
},
conditions: [
{ currentTime: 0, progress: 0.5 },
{ currentTime: 999, progress: 0.5 },
{ currentTime: 1000, progress: 0.5 },
{ currentTime: 1249, progress: 0.5 },
{ currentTime: 1250, progress: 1 },
{ currentTime: 1749, progress: 1 },
{ currentTime: 1750, progress: 0.5 },
{ currentTime: 2000, progress: 0.5 },
{ currentTime: 2500, progress: 0.5 },
]
},
{
description: 'Test bounds point of step-start easing ' +
'with iterationStart and delay',
effect: {
delay: 1000,
duration: 1000,
fill: 'both',
iterationStart: 0.5,
easing: 'steps(2, start)'
},
conditions: [
{ currentTime: 0, progress: 0.5 },
{ currentTime: 999, progress: 0.5 },
{ currentTime: 1000, progress: 1 },
{ currentTime: 1499, progress: 1 },
{ currentTime: 1500, progress: 0.5 },
{ currentTime: 2000, progress: 1 }
]
},
{
description: 'Test bounds point of step-start easing ' +
'with iterationStart and reverse direction',
effect: {
delay: 1000,
duration: 1000,
fill: 'both',
iterationStart: 0.5,
direction: 'reverse',
easing: 'steps(2, start)'
},
conditions: [
{ currentTime: 0, progress: 1 },
{ currentTime: 1000, progress: 1 },
{ currentTime: 1001, progress: 0.5 },
{ currentTime: 1499, progress: 0.5 },
{ currentTime: 1500, progress: 1 },
{ currentTime: 1999, progress: 1 },
{ currentTime: 2000, progress: 0.5 },
{ currentTime: 2500, progress: 0.5 }
]
},
{
description: 'Test bounds point of step(4, start) easing ' +
'with iterationStart 0.75 and delay',
effect: {
duration: 1000,
fill: 'both',
delay: 1000,
iterationStart: 0.75,
easing: 'steps(4, start)'
},
conditions: [
{ currentTime: 0, progress: 0.75 },
{ currentTime: 999, progress: 0.75 },
{ currentTime: 1000, progress: 1 },
{ currentTime: 2000, progress: 1 },
{ currentTime: 2500, progress: 1 }
]
},
{
description: 'Test bounds point of step-start easing ' +
'with alternate direction',
effect: {
duration: 1000,
fill: 'both',
delay: 1000,
iterations: 2,
iterationStart: 1.5,
direction: 'alternate',
easing: 'steps(2, start)'
},
conditions: [
{ currentTime: 0, progress: 1 },
{ currentTime: 1000, progress: 1 },
{ currentTime: 1001, progress: 0.5 },
{ currentTime: 2999, progress: 1 },
{ currentTime: 3000, progress: 0.5 },
{ currentTime: 3500, progress: 0.5 }
]
},
{
description: 'Test bounds point of step-start easing ' +
'with alternate-reverse direction',
effect: {
duration: 1000,
fill: 'both',
delay: 1000,
iterations: 2,
iterationStart: 0.5,
direction: 'alternate-reverse',
easing: 'steps(2, start)'
},
conditions: [
{ currentTime: 0, progress: 1 },
{ currentTime: 1000, progress: 1 },
{ currentTime: 1001, progress: 0.5 },
{ currentTime: 2999, progress: 1 },
{ currentTime: 3000, progress: 0.5 },
{ currentTime: 3500, progress: 0.5 }
]
},
{
description: 'Test bounds point of step-end easing',
effect: {
delay: 1000,
duration: 1000,
fill: 'both',
easing: 'steps(2, end)'
},
conditions: [
{ currentTime: 0, progress: 0 },
{ currentTime: 999, progress: 0 },
{ currentTime: 1000, progress: 0 },
{ currentTime: 1499, progress: 0 },
{ currentTime: 1500, progress: 0.5 },
{ currentTime: 2000, progress: 1 }
]
},
{
description: 'Test bounds point of step-end easing ' +
'with iterationStart and delay',
effect: {
duration: 1000,
fill: 'both',
delay: 1000,
iterationStart: 0.5,
easing: 'steps(2, end)'
},
conditions: [
{ currentTime: 0, progress: 0 },
{ currentTime: 999, progress: 0 },
{ currentTime: 1000, progress: 0.5 },
{ currentTime: 1499, progress: 0.5 },
{ currentTime: 1500, progress: 0 },
{ currentTime: 1999, progress: 0 },
{ currentTime: 2000, progress: 0.5 },
{ currentTime: 2500, progress: 0.5 }
]
},
{
description: 'Test bounds point of step-end easing ' +
'with iterationStart not at a transition point',
effect: {
delay: 1000,
duration: 1000,
fill: 'both',
iterationStart: 0.75,
easing: 'steps(2, end)'
},
conditions: [
{ currentTime: 0, progress: 0.5 },
{ currentTime: 999, progress: 0.5 },
{ currentTime: 1000, progress: 0.5 },
{ currentTime: 1249, progress: 0.5 },
{ currentTime: 1250, progress: 0 },
{ currentTime: 1749, progress: 0 },
{ currentTime: 1750, progress: 0.5 },
{ currentTime: 2000, progress: 0.5 },
{ currentTime: 2500, progress: 0.5 },
]
},
{
description: 'Test bounds point of steps(jump-both) easing',
effect: {
delay: 1000,
duration: 1000,
fill: 'both',
easing: 'steps(2, jump-both)'
},
conditions: [
{ currentTime: 0, progress: 0 },
{ currentTime: 999, progress: 0 },
{ currentTime: 1000, progress: 1/3 },
{ currentTime: 1499, progress: 1/3 },
{ currentTime: 1500, progress: 2/3 },
{ currentTime: 2000, progress: 1 }
]
},
{
description: 'Test bounds point of steps(jump-both) easing ' +
'with iterationStart and delay',
effect: {
duration: 1000,
fill: 'both',
delay: 1000,
iterationStart: 0.5,
easing: 'steps(2, jump-both)'
},
conditions: [
{ currentTime: 0, progress: 1/3 },
{ currentTime: 999, progress: 1/3 },
{ currentTime: 1000, progress: 2/3 },
{ currentTime: 1499, progress: 2/3 },
{ currentTime: 1500, progress: 1/3 },
{ currentTime: 1999, progress: 1/3 },
{ currentTime: 2000, progress: 2/3 },
{ currentTime: 2500, progress: 2/3 }
]
},
{
description: 'Test bounds point of steps(jump-both) easing ' +
'with iterationStart not at a transition point',
effect: {
delay: 1000,
duration: 1000,
fill: 'both',
iterationStart: 0.75,
easing: 'steps(2, jump-both)'
},
conditions: [
{ currentTime: 0, progress: 2/3 },
{ currentTime: 999, progress: 2/3 },
{ currentTime: 1000, progress: 2/3 },
{ currentTime: 1249, progress: 2/3 },
{ currentTime: 1250, progress: 1/3 },
{ currentTime: 1749, progress: 1/3 },
{ currentTime: 1750, progress: 2/3 },
{ currentTime: 2000, progress: 2/3 },
{ currentTime: 2500, progress: 2/3 }
]
},
{
description: 'Test bounds point of steps(jump-none) easing',
effect: {
delay: 1000,
duration: 1000,
fill: 'both',
easing: 'steps(2, jump-none)'
},
conditions: [
{ currentTime: 0, progress: 0 },
{ currentTime: 1000, progress: 0 },
{ currentTime: 1499, progress: 0 },
{ currentTime: 1500, progress: 1 },
{ currentTime: 2000, progress: 1 }
]
},
{
description: 'Test bounds point of steps(jump-none) easing ' +
'with iterationStart and delay',
effect: {
duration: 1000,
fill: 'both',
delay: 1000,
iterationStart: 0.5,
easing: 'steps(2, jump-none)'
},
conditions: [
{ currentTime: 0, progress: 0 },
{ currentTime: 999, progress: 0 },
{ currentTime: 1000, progress: 1 },
{ currentTime: 1499, progress: 1 },
{ currentTime: 1500, progress: 0 },
{ currentTime: 1999, progress: 0 },
{ currentTime: 2000, progress: 1 },
{ currentTime: 2500, progress: 1 }
]
},
{
description: 'Test bounds point of steps(jump-none) easing ' +
'with iterationStart not at a transition point',
effect: {
delay: 1000,
duration: 1000,
fill: 'both',
iterationStart: 0.75,
easing: 'steps(2, jump-none)'
},
conditions: [
{ currentTime: 0, progress: 1 },
{ currentTime: 999, progress: 1 },
{ currentTime: 1000, progress: 1 },
{ currentTime: 1249, progress: 1 },
{ currentTime: 1250, progress: 0 },
{ currentTime: 1749, progress: 0 },
{ currentTime: 1750, progress: 1 },
{ currentTime: 2000, progress: 1 },
{ currentTime: 2500, progress: 1 }
]
},
];
for (const options of gStepTimingFunctionTests) {
test(t => {
const target = createDiv(t);
const animation = target.animate(null, options.effect);
for (const condition of options.conditions) {
animation.currentTime = condition.currentTime;
assert_equals(animation.effect.getComputedTiming().progress,
condition.progress,
`Progress at ${animation.currentTime}ms`);
}
}, options.description);
}
test(t => {
const target = createDiv(t);
const anim = target.animate(
[
{ easing: 'steps(1, start)', opacity: 0 },
{ opacity: 1 }
],
{ easing: 'linear(-2, 2)', duration: 1000, fill: 'both' });
anim.currentTime = 0;
assert_equals(anim.effect.getComputedTiming().progress, -2);
// Input < 0 ==> output = 0.
assert_equals(getComputedStyle(target).opacity, "0");
anim.currentTime = 500;
assert_equals(anim.effect.getComputedTiming().progress, 0);
// Input = 0 & before flag = false ==> output = 1.
assert_equals(getComputedStyle(target).opacity, "1");
anim.currentTime = 1000;
// Input > 0 & before flag = false ==> output = 1.
assert_equals(anim.effect.getComputedTiming().progress, 2);
assert_equals(getComputedStyle(target).opacity, "1");
}, 'Test global timing function with values outside [0,1] with a step ' +
'timing function on the keyframe');
</script>
</body>