矩阵不等于css变换动画中的平移和旋转组合



@keyframes gray {
0% { transform: matrix(1, 0, 0, 1, 0, 0) }
100% { transform: matrix(-1, 0, 0, -1, 20, 20) }
}
@keyframes lightblue {
0% { transform: translate(10px, 10px) rotate(0deg) translate(-10px, -10px); }
100% { transform: translate(10px, 10px) rotate(180deg) translate(-10px, -10px); }
}
.gray {
float: left;
margin-left: 50px;
width: 20px;
height: 20px;
background: gray;
transform-origin: 0px 0px;
animation: gray linear 1s infinite;
}
.lightblue {
float: left;
margin-left: 50px;
width: 20px;
height: 20px;
background: lightblue;
transform-origin: 0px 0px;
animation: lightblue linear 1s infinite;
}
<div class="gray"></div>
<div class="lightblue"></div>

正如我所知

transform: matrix(1, 0, 0, 1, 0, 0);

等于

transform: translate(10px, 10px) rotate(0deg) translate(-10px, -10px);

transform: matrix(-1, 0, 0, -1, 20, 20)

等于

transform: translate(10px, 10px) rotate(180deg) translate(-10px, -10px);

当我直接对元素使用上面的css规则时,任何东西都可以正常工作。但当我在关键帧中使用上述css规则后,事情就出了问题。灰色元素的旋转角度不同于浅蓝色元素。

我在chrome 71 中测试代码

问题是浏览器将如何处理插值。两个矩阵都很好,它们与定义的变换相同,但两者之间的插值不同。

使用forwards而不是infinite可以看到两者都将以相同的状态开始和结束:

@keyframes gray {
0% { transform: matrix(1, 0, 0, 1, 0, 0) }
100% { transform: matrix(-1, 0, 0, -1, 20, 20) }
}
@keyframes lightblue {
0% { transform: translate(10px, 10px) rotate(0deg) translate(-10px, -10px); }
100% { transform: translate(10px, 10px) rotate(180deg) translate(-10px, -10px); }
}
.gray {
float: left;
margin-left: 50px;
width: 20px;
height: 20px;
background: gray;
transform-origin: 0px 0px;
animation: gray linear 2s 0.5s forwards;
border-right:2px solid;
}
.lightblue {
float: left;
margin-left: 50px;
width: 20px;
height: 20px;
background: lightblue;
transform-origin: 0px 0px;
animation: lightblue linear 2s 0.5s forwards;
border-right:2px solid;
}
<div class="gray"></div>
<div class="lightblue"></div>

基本上,矩阵将首先分解为变换,然后进行插值。所以第一个matrix(1, 0, 0, 1, 0, 0),也就是恒等式,将被转换为空转换(例如scale(1,1)rotate(0)),而不是像你想象的translate(10px, 10px) rotate(0deg) translate(-10px, -10px)。则可以将第二个CCD_ 9转换为CCD_。同样,它不会是translate(10px, 10px) rotate(180deg) translate(-10px, -10px)

现在很明显,两个动画的插值(中间状态)将不相同。这是因为浏览器不会使用与定义矩阵时相同的转换。理论上,有无限数量的组合,浏览器会使用自己的算法来找到他将使用的算法,而不一定是你定义的算法。

您可以查看此链接以了解更多详细信息:https://drafts.csswg.org/css-transforms/#interpolation-转换

以下是我们如何使两者相同的示例:

@keyframes gray {
0% { transform: matrix(1, 0, 0, 1, 0, 0) }
100% { transform: matrix(-1, 0, 0, -1, 20, 20) }
}
@keyframes lightblue {
0% { transform: scale(1,1) }
100% { transform:scale(-1,-1) translate(-20px, -20px)  ; }
}
.gray {
float: left;
margin-left: 50px;
width: 20px;
height: 20px;
background: gray;
transform-origin: 0px 0px;
animation: gray linear 2s 0.5s infinite;
border-right:2px solid;
}
.lightblue {
float: left;
margin-left: 50px;
width: 20px;
height: 20px;
background: lightblue;
transform-origin: 0px 0px;
animation: lightblue linear 2s 0.5s infinite;
border-right:2px solid;
}
<div class="gray"></div>
<div class="lightblue"></div>

最新更新