CSS 动画中旋转和平移是如何工作的?
How does rotation combined with translation work inside CSS animation?
我在codepen上看到这个动画,不知道为什么要这样写才能有这个效果,不过我觉得应该是顺时针旋转360deg,逆时针旋转360deg的效果,而不是往上弹跳向下或向左和向右
我对这些关键帧动画特别迷惑
@keyframes move{
from {
transform: rotate(360deg) translateX(1.125em) rotate(-360deg);
}
to {
transform: rotate(-360deg) translateX(1.125em) rotate(360deg);
}
}
结果如下
https://i.stack.imgur.com/9oWnw.gif
从the specification我们可以看出浏览器应该如何处理transform
值之间的插值。在这种情况下,我们使用这个:
If from- and to-transform have the same number of transform functions,
each transform function pair has either the same name, or is a
derivative of the same primitive: Interpolate each transform function
pair as described in Interpolation of transform functions. The
computed value is the resulting transform function list.
因此浏览器会将第一个 rotate
从 360deg
更改为 -360deg
,最后一个 rotate
也相同,而 translateX
将保持不变.然后我们将有以下步骤:
transform: rotate(360deg) translateX(1.125em) rotate(-360deg);
transform: rotate(350deg) translateX(1.125em) rotate(-350deg);
transform: rotate(340deg) translateX(1.125em) rotate(-340deg);
....
transform: rotate(0) translateX(1.125em) rotate(0);
....
....
transform: rotate(-360deg) translateX(1.125em) rotate(360deg);
现在我们需要了解 rotate(-adeg) translateX(b) rotate(adeg)
的工作原理。首先,您可能会注意到旋转不会对元素产生任何视觉效果,因为我们处理的是圆,它只会影响平移的工作方式,更准确地说,这是第一次旋转这很重要(左边那个)。
.container {
width: 50px;
height: 50px;
margin: 50px;
border:2px solid;
}
.box {
width: 50px;
height: 50px;
background: red;
border-radius: 50%;
animation: move 2s linear infinite;
}
.alt {
animation: move-alt 2s linear infinite;
}
@keyframes move {
from {
transform: rotate(360deg) translateX(1.125em) rotate(-360deg);
}
to {
transform: rotate(-360deg) translateX(1.125em) rotate(360deg);
}
}
@keyframes move-alt {
from {
transform: rotate(360deg) translateX(1.125em);
}
to {
transform: rotate(-360deg) translateX(1.125em);
}
}
<div class="container">
<div class="box">
</div>
</div>
<div class="container">
<div class="box alt">
</div>
</div>
如您所见,两个动画在视觉上是等价的。
现在的效果如下:每次我们旋转 X 轴然后我们平移我们的元素时考虑新的旋转轴。这就像我们旋转坐标系然后我们平移或者就像我们平移一次(因为它是相同的)然后我们继续旋转坐标系因此我们在最后有一个旋转。
现在如果我们考虑相反的变换,视觉上不会发生任何事情:
.container {
width: 50px;
height: 50px;
margin: 50px;
border: 2px solid;
}
.box {
width: 50px;
height: 50px;
background: red;
border-radius: 50%;
animation: move 2s linear infinite;
}
@keyframes move {
from {
transform: translateX(1.125em) rotate(-360deg);
}
to {
transform: translateX(1.125em) rotate(360deg);
}
}
<div class="container">
<div class="box">
</div>
</div>
在这种情况下,我们通过相同的平移来平移坐标系,然后旋转我们的圆。如果我们把它改成正方形我们会看到效果
.container {
width: 50px;
height: 50px;
margin: 50px;
border: 2px solid;
}
.box {
width: 50px;
height: 50px;
background: red;
animation: move 2s linear infinite;
}
@keyframes move {
from {
transform: translateX(1.125em) rotate(-360deg);
}
to {
transform: translateX(1.125em) rotate(360deg);
}
}
<div class="container">
<div class="box">
</div>
</div>
这是您的初始动画与正方形的外观:
.container {
width: 50px;
height: 50px;
margin: 50px;
border: 2px solid;
}
.box {
width: 50px;
height: 50px;
background: red;
animation: move 2s linear infinite;
}
@keyframes move {
from {
transform:rotate(360deg) translateX(1.125em) rotate(-360deg);
}
to {
transform:rotate(-360deg) translateX(1.125em) rotate(360deg);
}
}
<div class="container">
<div class="box">
</div>
</div>
我们旋转坐标系,平移元素,然后旋转元素,就好像我们在一个更大的元素内旋转元素,而这个元素也在向相反的方向旋转。
如果您将计时功能更改为线性以外的其他功能,您将拥有相同的旋转,但它不是线性的,它将在某个时间间隔内变为 slower/faster:
.container {
width: 50px;
height: 50px;
margin: 50px;
border: 2px solid;
}
.box {
width: 50px;
height: 50px;
background: red;
animation: move 2s ease-in-out infinite;
}
@keyframes move {
from {
transform:rotate(360deg) translateX(1.125em) rotate(-360deg);
}
to {
transform:rotate(-360deg) translateX(1.125em) rotate(360deg);
}
}
<div class="container">
<div class="box">
</div>
</div>
这是一个简化的解释,如果您想了解更多有关我们如何处理 transform 中的多个函数以及顺序如何重要的详细信息,您可以查看此答案:
我在codepen上看到这个动画,不知道为什么要这样写才能有这个效果,不过我觉得应该是顺时针旋转360deg,逆时针旋转360deg的效果,而不是往上弹跳向下或向左和向右
我对这些关键帧动画特别迷惑
@keyframes move{
from {
transform: rotate(360deg) translateX(1.125em) rotate(-360deg);
}
to {
transform: rotate(-360deg) translateX(1.125em) rotate(360deg);
}
}
结果如下
https://i.stack.imgur.com/9oWnw.gif
从the specification我们可以看出浏览器应该如何处理transform
值之间的插值。在这种情况下,我们使用这个:
If from- and to-transform have the same number of transform functions, each transform function pair has either the same name, or is a derivative of the same primitive: Interpolate each transform function pair as described in Interpolation of transform functions. The computed value is the resulting transform function list.
因此浏览器会将第一个 rotate
从 360deg
更改为 -360deg
,最后一个 rotate
也相同,而 translateX
将保持不变.然后我们将有以下步骤:
transform: rotate(360deg) translateX(1.125em) rotate(-360deg);
transform: rotate(350deg) translateX(1.125em) rotate(-350deg);
transform: rotate(340deg) translateX(1.125em) rotate(-340deg);
....
transform: rotate(0) translateX(1.125em) rotate(0);
....
....
transform: rotate(-360deg) translateX(1.125em) rotate(360deg);
现在我们需要了解 rotate(-adeg) translateX(b) rotate(adeg)
的工作原理。首先,您可能会注意到旋转不会对元素产生任何视觉效果,因为我们处理的是圆,它只会影响平移的工作方式,更准确地说,这是第一次旋转这很重要(左边那个)。
.container {
width: 50px;
height: 50px;
margin: 50px;
border:2px solid;
}
.box {
width: 50px;
height: 50px;
background: red;
border-radius: 50%;
animation: move 2s linear infinite;
}
.alt {
animation: move-alt 2s linear infinite;
}
@keyframes move {
from {
transform: rotate(360deg) translateX(1.125em) rotate(-360deg);
}
to {
transform: rotate(-360deg) translateX(1.125em) rotate(360deg);
}
}
@keyframes move-alt {
from {
transform: rotate(360deg) translateX(1.125em);
}
to {
transform: rotate(-360deg) translateX(1.125em);
}
}
<div class="container">
<div class="box">
</div>
</div>
<div class="container">
<div class="box alt">
</div>
</div>
如您所见,两个动画在视觉上是等价的。
现在的效果如下:每次我们旋转 X 轴然后我们平移我们的元素时考虑新的旋转轴。这就像我们旋转坐标系然后我们平移或者就像我们平移一次(因为它是相同的)然后我们继续旋转坐标系因此我们在最后有一个旋转。
现在如果我们考虑相反的变换,视觉上不会发生任何事情:
.container {
width: 50px;
height: 50px;
margin: 50px;
border: 2px solid;
}
.box {
width: 50px;
height: 50px;
background: red;
border-radius: 50%;
animation: move 2s linear infinite;
}
@keyframes move {
from {
transform: translateX(1.125em) rotate(-360deg);
}
to {
transform: translateX(1.125em) rotate(360deg);
}
}
<div class="container">
<div class="box">
</div>
</div>
在这种情况下,我们通过相同的平移来平移坐标系,然后旋转我们的圆。如果我们把它改成正方形我们会看到效果
.container {
width: 50px;
height: 50px;
margin: 50px;
border: 2px solid;
}
.box {
width: 50px;
height: 50px;
background: red;
animation: move 2s linear infinite;
}
@keyframes move {
from {
transform: translateX(1.125em) rotate(-360deg);
}
to {
transform: translateX(1.125em) rotate(360deg);
}
}
<div class="container">
<div class="box">
</div>
</div>
这是您的初始动画与正方形的外观:
.container {
width: 50px;
height: 50px;
margin: 50px;
border: 2px solid;
}
.box {
width: 50px;
height: 50px;
background: red;
animation: move 2s linear infinite;
}
@keyframes move {
from {
transform:rotate(360deg) translateX(1.125em) rotate(-360deg);
}
to {
transform:rotate(-360deg) translateX(1.125em) rotate(360deg);
}
}
<div class="container">
<div class="box">
</div>
</div>
我们旋转坐标系,平移元素,然后旋转元素,就好像我们在一个更大的元素内旋转元素,而这个元素也在向相反的方向旋转。
如果您将计时功能更改为线性以外的其他功能,您将拥有相同的旋转,但它不是线性的,它将在某个时间间隔内变为 slower/faster:
.container {
width: 50px;
height: 50px;
margin: 50px;
border: 2px solid;
}
.box {
width: 50px;
height: 50px;
background: red;
animation: move 2s ease-in-out infinite;
}
@keyframes move {
from {
transform:rotate(360deg) translateX(1.125em) rotate(-360deg);
}
to {
transform:rotate(-360deg) translateX(1.125em) rotate(360deg);
}
}
<div class="container">
<div class="box">
</div>
</div>
这是一个简化的解释,如果您想了解更多有关我们如何处理 transform 中的多个函数以及顺序如何重要的详细信息,您可以查看此答案: