| <!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> |