为什么此关键帧动画形成此动画效果

时间:2018-10-05 10:39:37

标签: css css3 css-animations css-transforms

我在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

1 个答案:

答案 0 :(得分:0)

the specification中,我们可以看到浏览器应如何处理transform值之间的插值。在这种情况下,我们使用以下代码:

  

如果from-和to-transform具有相同数量的转换函数,   每个转换函数对具有相同的名称,或者是   相同基元的派生:插值每个变换函数   对,如变换函数的插值中所述。的   计算值就是转换函数列表。

因此,浏览器会将第一个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轴然后平移元素时,请考虑新的旋转轴。就像我们先旋转坐标系然后进行平移,还是像平移一次(因为它是相同的)一样进行平移,然后我们继续旋转坐标系,从而最后进行旋转。

enter image description here

现在,如果我们考虑相反的转换,则在视觉上什么也不会发生:

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

我们旋转坐标系,先平移元素,然后旋转元素,这样就好像我们在更大的元素内旋转元素一样,该元素也朝相反的方向旋转。

如果您将计时功能更改为线性以外的其他功能,则您将具有相同的旋转度,但不会是线性的,那么它将在一定的间隔内变慢/变快:

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


这是一个简化的说明,如果您想了解有关我们如何处理转换中的多重功能以及顺序如何重要的更多详细信息,请检查以下答案:Simulating transform-origin using translate