blob: 4a71ea0a8d2ea2bcf7e115a02603b3af70911634 [file] [log] [blame]
<!DOCTYPE html>
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>
<style>
#box {
position: relative;
height: 100px;
width: 100px;
background-color: blue;
transition-delay: 0s;
transition-duration: 1s;
transition-property: width;
transition-timing-function: ease;
}
#box.target, #box:hover {
width: 200px;
}
</style>
<div id="box"></div>
<script>
function assert_px_approx_equals(actual, expected, epsilon, description) {
var match = /^([\d.]+)px$/.exec(actual);
assert_not_equals(match, null);
assert_approx_equals(Number(match[1]), expected, epsilon, description);
}
test(function() {
var box = document.getElementById('box');
assert_equals(getComputedStyle(box).width, '100px', 'initial width');
// Start the animation.
box.className = 'target';
getComputedStyle(box).width; // Force the transition.
var animation = box.getAnimations()[0];
animation.pause();
animation.currentTime = 0;
assert_equals(getComputedStyle(box).width, '100px', 'width at transition start');
animation.currentTime = 400;
// cubicBezier(0.25, 0.1, 0.25, 1)(0.4) = 0.68254
assert_px_approx_equals(getComputedStyle(box).width, 168.254, 0.01, 'width mid-forward');
// Reverse the animation.
box.className = '';
getComputedStyle(box).width; // Force the transition.
animation = box.getAnimations()[0];
animation.pause(); // The animation is replaced, so pause it again.
animation.currentTime = 0;
assert_px_approx_equals(getComputedStyle(box).width, 168.254, 0.01, 'width after className');
// https://drafts.csswg.org/css-transitions-1/#reversing
// Reversing an animation.
// reverse shortening factor = output of timing function = 0.68254
// start time = (now)
// end time = (now) + duration * shortening factor = (now) + 682.54ms
// start value = 168.254
// end value = 100
// progress = 200 / (end time - start time) = 0.2930
// timing output = cubicBezier(0.25, 0.1, 0.25, 1)(0.2930) = 0.49939
// Expected position = (end value - start value) * timing output + start value = 134.165.
animation.currentTime = 200;
assert_px_approx_equals(getComputedStyle(box).width, 134.165, 0.01, 'width mid-reverse');
// Go forward again. This tests the reversingAdjustedStartValue is set
// properly the first time it's reversed.
box.className = 'target';
getComputedStyle(box).width; // Force the transition.
animation = box.getAnimations()[0];
animation.pause(); // The animation is replaced, so pause it again.
animation.currentTime = 0;
assert_px_approx_equals(getComputedStyle(box).width, 134.165, 0.01, 'width after second reverse');
// reverse shortening factor
// = (output of timing function) * (old shortening factor) +
// (1 - old shortening factor) = 0.65831
// start time = (now)
// end time = (now) + duration * shortening factor = (now) + 658.31ms
// start value = 134.168
// end value = 200
// progress = 400 / (end time - start time) = 0.60761
// timing output = cubicBezier(0.25, 0.1, 0.25, 1)(0.6076) = 0.89032
// Expected position = (end value - start value) * timing output + start value = 192.779
// Accumulated a bit of round off error at this stage of the calculation. Relaxing the tolerance.
animation.currentTime = 400;
assert_px_approx_equals(getComputedStyle(box).width, 192.779, 0.02, 'width mid-second-reverse');
animation.currentTime = 800;
assert_equals(getComputedStyle(box).width, '200px', 'width at end');
assert_equals(box.getAnimations().length, 0, 'animation ended');
}, "Check that reversing a transition (with ease timing function) mid-way adjusts the duration");
</script>