blob: 879a56e9f7cda3d15ddabd1e888975dbd8e551dc [file] [log] [blame]
<!DOCTYPE html>
<meta charset="UTF-8">
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>
<div id="target"></div>
<script>
// These tests target post multiplication interpolation behaviour of the transform property.
// https://drafts.csswg.org/css-transforms-1/#interpolation-of-transforms
function assertPostMultiplication(start, end) {
test(() => {
assert_true(interpolationUsesPostMultiplication(start, end));
}, 'Animating transform from ' + start + ' to ' + end + ' should use post multiplication');
}
function assertNoPostMultiplication(start, end) {
test(() => {
assert_false(interpolationUsesPostMultiplication(start, end));
}, 'Animating transform from ' + start + ' to ' + end + ' should not use post multiplication');
}
function interpolationUsesPostMultiplication(start, end) {
// This value prefix will cause post multiplication to interpolate differently than pairwise interpolation.
var testStart = 'rotate(90deg) translateX(10px) ' + start;
var testEnd = 'rotate(90deg) translateX(100px) ' + end;
var animation = target.animate({transform: [toMatrix(testStart), toMatrix(testEnd)]}, 1);
animation.currentTime = 0.5;
var postMultipliedInterpolation = getComputedStyle(target).transform;
animation.cancel();
animation = target.animate({transform: [testStart, testEnd]}, 1);
animation.currentTime = 0.5;
var interpolation = getComputedStyle(target).transform;
animation.cancel();
return matricesApproxEqual(interpolation, postMultipliedInterpolation, 0.01);
}
function toMatrix(transform) {
target.style.transform = transform;
var matrix = getComputedStyle(target).transform;
target.style.transform = '';
return matrix;
}
function matricesApproxEqual(actualMatrix, expectedMatrix, epsilon) {
var actualNumbers = actualMatrix.split(/[^\d\.-]/).map(Number);
var expectedNumbers = expectedMatrix.split(/[^\d\.-]/).map(Number);
if (actualNumbers.length !== expectedNumbers.length) {
return false;
}
for (var i = 0; i < actualNumbers.length; i++) {
if (Math.abs(actualNumbers[i] - expectedNumbers[i]) > epsilon) {
return false;
}
}
return true;
}
assertPostMultiplication('translateX(10px)', 'matrix(1, 1, 1, 1, 1, 1)');
assertPostMultiplication('translateX(10px)', 'rotate(90deg)');
assertPostMultiplication('skewX(90deg)', 'skewY(90deg)');
assertPostMultiplication('skew(90deg, 0deg)', 'skewY(90deg)');
assertPostMultiplication('matrix(1, 0, 0, 1, 0, 0)', 'matrix3d(2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 4, 0, 0, 0, 0, 1)');
assertNoPostMultiplication('translate(10px, 20px)', 'translateX(100px)');
assertNoPostMultiplication('translateX(10px)', 'translateY(100px)');
assertNoPostMultiplication('translateX(10px)', 'translateZ(100px)');
assertNoPostMultiplication('translateZ(10px)', 'translate3d(100px, 20px, 30px)');
assertNoPostMultiplication('scaleX(2)', 'scaleY(1)');
assertNoPostMultiplication('scaleX(2)', 'scaleZ(1)');
assertNoPostMultiplication('scaleX(2)', 'scale(1, 2)');
assertNoPostMultiplication('scaleX(2)', 'scale3d(1, 2, 3)');
assertNoPostMultiplication('skewY(10deg)', 'skewY(90deg)');
assertNoPostMultiplication('rotate(10deg)', 'rotate(90deg)');
assertNoPostMultiplication('rotateY(10deg)', 'rotateY(90deg)');
assertNoPostMultiplication('rotateX(90deg)', 'rotateY(90deg)');
assertNoPostMultiplication('rotate(10deg)', 'rotate3d(1, 2, 1, 90deg)');
assertNoPostMultiplication('rotate(10deg)', 'rotateZ(90deg)');
assertNoPostMultiplication('rotate(10deg)', 'rotate3d(0, 0, 1, 90deg)');
assertNoPostMultiplication('rotate(10deg)', 'rotate3d(0, 0, 2, 90deg)');
assertNoPostMultiplication('rotateX(10deg)', 'rotate3d(1, 0, 0, 100deg)');
assertNoPostMultiplication('perspective(10px)', 'perspective(100px)');
assertNoPostMultiplication('matrix(1, 0, 0, 1, 0, 0)', 'matrix(2, 0, 0, 2, 0, 0)');
</script>