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.

因此浏览器会将第一个 rotate360deg 更改为 -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 中的多个函数以及顺序如何重要的详细信息,您可以查看此答案: