矩阵不等于 css 变换动画中的平移和旋转组合?
matrix not equal to translate and rotate combination in css transform animation?
@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 规则之后,事情就出错了。
灰色元素的旋转角度与浅蓝色元素不同
我测试了chrome71
中的代码
问题在于浏览器将如何处理插值。两个矩阵都很好,它们与定义的变换相同,但两者之间的插值不同。
使用 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)
。那么第二个matrix(-1, 0, 0, -1, 20, 20)
可以转化为scale(-1,-1) translate(-20px,-20px)
。同样不会是 translate(10px, 10px) rotate(180deg) translate(-10px, -10px)
.
现在很明显,两个动画的插值(中间状态)将不相同。这是因为浏览器不会使用您用于定义矩阵的相同转换。理论上,有无限多种组合,浏览器会使用自己的算法找到他要使用的一种,不一定是你定义的那种。
您可以查看此 link 了解更多详情:https://drafts.csswg.org/css-transforms/#interpolation-of-transforms
这是一个我们如何使两者相同的示例:
@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>
@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 规则之后,事情就出错了。 灰色元素的旋转角度与浅蓝色元素不同
我测试了chrome71
中的代码问题在于浏览器将如何处理插值。两个矩阵都很好,它们与定义的变换相同,但两者之间的插值不同。
使用 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)
。那么第二个matrix(-1, 0, 0, -1, 20, 20)
可以转化为scale(-1,-1) translate(-20px,-20px)
。同样不会是 translate(10px, 10px) rotate(180deg) translate(-10px, -10px)
.
现在很明显,两个动画的插值(中间状态)将不相同。这是因为浏览器不会使用您用于定义矩阵的相同转换。理论上,有无限多种组合,浏览器会使用自己的算法找到他要使用的一种,不一定是你定义的那种。
您可以查看此 link 了解更多详情:https://drafts.csswg.org/css-transforms/#interpolation-of-transforms
这是一个我们如何使两者相同的示例:
@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>