【问题标题】:Pure CSS rotate animation broken while in infinite loop纯CSS旋转动画在无限循环中被破坏
【发布时间】:2019-11-03 01:37:05
【问题描述】:

我已经有一段时间没有在这里提问了。所以,如果我做错了什么,请原谅。

我对 CSS 动画 有疑问。我希望我的动画不断自我重复,但不会失去初始效果。但是,我的代码或 CSS 动画行为中似乎存在错误。

在完成前 2 个旋转动画(自旋、自旋) 定义后。循环开始,但新的动画与以前不同。

我的目标按顺序在 6 个框上创建旋转动画,一次一个。当所有的盒子都转动时,它们应该重新开始转动到原来的状态,一个接一个。

代码:

/* -------------------------------------------------------- */
#loader {
  width: 240px;
  height: 100px;
}

.inner {
  position: relative;
  width: 100%;
  height: 100%;
  text-align: center;
  transition: transform 2s;
  transform-style: preserve-3d;
  background-color: transparent;
}

.front,
.back {
  position: absolute;
  width: 80px;
  height: 50px;
  backface-visibility: hidden;
}


/* -------------------------------------------------------- */

#loader1 {
  float: left;
  width: 80px;
  height: 50px;
  perspective: 1000px;
  background-color: transparent;
}

#loader1 .inner {
  animation: spin 10s ease 0s infinite, spinback 10s ease 10s infinite;
  -webkit-animation: spin 10s ease 0s infinite, spinback 10s ease 10s infinite;
}

#loader1 .front {
  background-color: #db9834;
}

#loader1 .back {
  background-color: #3498db;
  transform: rotateY(180deg);
}


/* -------------------------------------------------------- */

#loader2 {
  float: left;
  width: 80px;
  height: 50px;
  perspective: 1000px;
  background-color: transparent;
}

#loader2 .inner {
  animation: spin 10s ease 1s infinite, spinback 10s ease 11s infinite;
  -webkit-animation: spin 10s ease 1s infinite, spinback 10s ease 11s infinite;
}

#loader2 .front {
  background-color: #db8834;
}

#loader2 .back {
  background-color: #3488db;
  transform: rotateY(180deg);
}


/* -------------------------------------------------------- */

#loader3 {
  float: left;
  width: 80px;
  height: 50px;
  perspective: 1000px;
  background-color: transparent;
}

#loader3 .inner {
  animation: spin 10s ease 2s infinite, spinback 10s ease 12s infinite;
  -webkit-animation: spin 10s ease 2s infinite, spinback 10s ease 12s infinite;
}

#loader3 .front {
  background-color: #db7834;
}

#loader3 .back {
  background-color: #3478db;
  transform: rotateY(180deg);
}


/* -------------------------------------------------------- */

#loader4 {
  float: left;
  width: 80px;
  height: 50px;
  perspective: 1000px;
  background-color: transparent;
}

#loader4 .inner {
  animation: spin 10s ease 3s infinite, spinback 10s ease 13s infinite;
  -webkit-animation: spin 10s ease 3s infinite, spinback 10s ease 13s infinite;
}

#loader4 .front {
  background-color: #db6834;
}

#loader4 .back {
  background-color: #3468db;
  transform: rotateY(180deg);
}


/* -------------------------------------------------------- */

#loader5 {
  float: left;
  width: 80px;
  height: 50px;
  perspective: 1000px;
  background-color: transparent;
}

#loader5 .inner {
  animation: spin 10s ease 4s infinite, spinback 10s ease 14s infinite;
  -webkit-animation: spin 10s ease 4s infinite, spinback 10s ease 14s infinite;
}

#loader5 .front {
  background-color: #db5834;
}

#loader5 .back {
  background-color: #3458db;
  transform: rotateY(180deg);
}


/* -------------------------------------------------------- */

#loader6 {
  float: left;
  width: 80px;
  height: 50px;
  perspective: 1000px;
  background-color: transparent;
}

#loader6 .inner {
  animation: spin 10s ease 5s infinite, spinback 10s ease 15s infinite;
  -webkit-animation: spin 10s ease 5s infinite, spinback 10s ease 15s infinite;
}

#loader6 .front {
  background-color: #db4834;
}

#loader6 .back {
  background-color: #3448db;
  transform: rotateY(180deg);
}

@-webkit-keyframes spin {
  0% {
    -webkit-transform: rotateY(0deg);
  }
  16% {
    -webkit-transform: rotateY(180deg);
  }
  100% {
    -webkit-transform: rotateY(180deg);
  }
}

@keyframes spin {
  0% {
    -webkit-transform: rotateY(0deg);
  }
  16% {
    -webkit-transform: rotateY(180deg);
  }
  100% {
    -webkit-transform: rotateY(180deg);
  }
}

@-webkit-keyframes spinback {
  0% {
    -webkit-transform: rotateY(180deg);
  }
  16% {
    -webkit-transform: rotateY(0deg);
  }
  100% {
    -webkit-transform: rotateY(0deg);
  }
}

@keyframes spinback {
  0% {
    -webkit-transform: rotateY(180deg);
  }
  16% {
    -webkit-transform: rotateY(0deg);
  }
  100% {
    -webkit-transform: rotateY(0deg);
  }
}
<div id="loader">
  <div id="loader1">
    <div class="inner">
      <div class="front">
      </div>
      <div class="back"> </div>
    </div>
  </div>
  <div id="loader2">
    <div class="inner">
      <div class="front"> </div>
      <div class="back"> </div>
    </div>
  </div>
  <div id="loader3">
    <div class="inner">
      <div class="front"> </div>
      <div class="back"> </div>
    </div>
  </div>
  <div id="loader4">
    <div class="inner">
      <div class="front"> </div>
      <div class="back"> </div>
    </div>
  </div>
  <div id="loader5">
    <div class="inner">
      <div class="front"> </div>
      <div class="back"> </div>
    </div>
  </div>
  <div id="loader6">
    <div class="inner">
      <div class="front"> </div>
      <div class="back"> </div>
    </div>
  </div>
</div>

为了更容易理解,我正在尝试应用 css 翻转卡方法:

https://www.w3schools.com/howto/howto_css_flip_card.asp

在 div 上创建一个看起来像是正在加载的东西......

动画只给出了在正确的时间触发关键帧的时间,然后在关键帧中我正在旋转 div 并等待时间,直到其他 div 完成旋转。所以公式是 10 秒内 6 个盒子,它会介于 (0% 到 100%) 之间,所以 (100 / 6 = 16,6) 我认为动画应该在动画时间的 16% 处结束。

【问题讨论】:

  • spin 10s ease 1s infinite, spinback 10s ease 11s infinite 这意味着我们等待 1 秒然后运行旋转 10 秒(同时我们等待 11 秒)然后我们运行回旋并且我们同时运行再次旋转(问题)跨度>

标签: html css css-animations


【解决方案1】:

首先我会简化您的代码并使用更少的 HTML/CSS。然后我会只考虑一个动画,我会同时拥有两种状态。

动画将是:第一次翻转,然后我们保留第一种颜色,然后第二次翻转,然后我们保留第二种颜色。分为12时隙(1 + 5 + 1 + 51+5 = 6是div的个数)

如果持续时间是S,那么延迟应该是一个槽S/12 的倍数。请注意,我在变换中使用了透视图来避免额外的元素:

#loader {
  width: 240px;
  height: 100px;
  display: flex;
  flex-wrap: wrap;
}

#loader>div {
  width: calc(100%/3);
  position: relative;
  transform-style: preserve-3d;
  animation: spin 6s linear var(--delay, 0s) infinite;
}

#loader>div:before,
#loader>div:after {
  content: "";
  position: absolute;
  top:0;
  left:0;
  width: 100%;
  height: 100%;
  backface-visibility: hidden;
  background-color: var(--front, #db9834);
}

#loader>div:after {
  background-color: var(--back, #3498db);
  transform: rotateY(180deg);
}


/* -------------------------------------------------------- */

#loader>div:nth-child(2) {
  --front: #db8834;
  --back: #3488db;
  --delay: 0.5s;
}

#loader>div:nth-child(3) {
  --front: #db7834;
  --back: #3478db;
  --delay: 1s;
}

#loader>div:nth-child(4) {
  --front: #db6834;
  --back: #3468db;
  --delay: 1.5s;
}

#loader>div:nth-child(5) {
  --front: #db5834;
  --back: #3458db;
  --delay: 2s;
}

#loader>div:nth-child(6) {
  --front: #db4834;
  --back: #3448db;
  --delay: 2.5s;
}


@keyframes spin {
  0% {
    transform:perspective(500px) rotateY(0deg);
  }
  8.33%,
  50%{
    transform:perspective(500px) rotateY(180deg);
  }
  58.33% {
    transform:perspective(500px) rotateY(0deg);
  }
}
<div id="loader">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
</div>

有关perspectiveperspective()之间区别的更多详细信息的相关问题

CSS 3d transform doesn't work if perspective is set in the end of property

perspective and translateZ moves diagonally


如果我们在旋转时改变 div 的颜色而不是两个元素,我们可以简化更多。应该在我们进行翻转(第一次和第六次)的一半位置进行更改,而不需要任何过渡来创建错觉:

#loader {
  width: 240px;
  height: 100px;
  display: flex;
  flex-wrap: wrap;
}

#loader>div {
  width: calc(100%/3);
  animation: 
    spin   6s linear var(--delay, 0s) infinite,
    colors 6s linear var(--delay, 0s) infinite;
  background-color: var(--front, #db9834);
}


/* -------------------------------------------------------- */

#loader>div:nth-child(2) {
  --front: #db8834;
  --back: #3488db;
  --delay: 0.5s;
}

#loader>div:nth-child(3) {
  --front: #db7834;
  --back: #3478db;
  --delay: 1s;
}

#loader>div:nth-child(4) {
  --front: #db6834;
  --back: #3468db;
  --delay: 1.5s;
}

#loader>div:nth-child(5) {
  --front: #db5834;
  --back: #3458db;
  --delay: 2s;
}

#loader>div:nth-child(6) {
  --front: #db4834;
  --back: #3448db;
  --delay: 2.5s;
}


@keyframes spin {
  0% {
    transform:perspective(500px) rotateY(0deg);
  }
  8.33%,
  50%{
    transform:perspective(500px) rotateY(180deg);
  }
  58.33% {
    transform:perspective(500px) rotateY(0deg);
  }
}
@keyframes colors {
  0%,4.15% {
    background-color: var(--front, #db9834);
  }
  4.16% {
    background-color: var(--back, #3498db);
  }
  54.15% {
    background-color: var(--back, #3498db);
  }
  54.16% {
    background-color: var(--front, #db9834);
  }
}
<div id="loader">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
</div>

考虑到您希望拥有相同的颜色深浅,可以使用过滤器进行另一个简化:

#loader {
  width: 240px;
  height: 100px;
  display: flex;
  flex-wrap: wrap;
}

#loader>div {
  width: calc(100%/3);
  animation: 
    spin   6s linear var(--delay, 0s) infinite,
    colors 6s linear var(--delay, 0s) infinite;
  background: 
    linear-gradient(#db9834 50%, #3498db 0);
  background-size: 100% 200%;
}


/* -------------------------------------------------------- */

#loader>div:nth-child(2) {
  filter: brightness(0.9);
  --delay: 0.5s;
}

#loader>div:nth-child(3) {
  filter: brightness(0.8);
  --delay: 1s;
}

#loader>div:nth-child(4) {
  filter: brightness(0.7);
  --delay: 1.5s;
}

#loader>div:nth-child(5) {
  filter: brightness(0.6);
  --delay: 2s;
}

#loader>div:nth-child(6) {
  filter: brightness(0.5);
  --delay: 2.5s;
}


@keyframes spin {
  0% {
    transform:perspective(500px) rotateY(0deg);
  }
  8.33%,
  50%{
    transform:perspective(500px) rotateY(180deg);
  }
  58.33% {
    transform:perspective(500px) rotateY(0deg);
  }
}
@keyframes colors {
  4.15% {
    background-position: top;
  }
  4.16%,
  54.15% {
    background-position:bottom;
  }
  54.16% {
    background-position: top;
  }

}
<div id="loader">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
</div>

这个结果与我使用随机过滤器的结果并不完全相同,但您可以轻松尝试另一种过滤以获得所需的结果。

【讨论】:

  • 哇!这比我期望的答案要多,这扩大了我的视野,非常感谢。 :D
  • 还有你可以提供的链接来教我更多关于这些类型的 css 变量用法的信息吗?这似乎是令人难以置信的高性能方式..
  • @BerkerYüceer 我并没有具体的链接,但我使用 CSS 变量 (stackoverflow.com/search?q=user%3A8620333+css+variables) 回答了很多问题,您可以找到更多技巧和详细信息
  • @BerkerYüceer 我可能给你的唯一外部链接是描述它们的官方规范:w3.org/TR/css-variables/#syntax
  • 第二个选项具有相同的颜色但不同的亮度级别是一个好方法,但是对于想要使用图像而不是颜色的人来说,为不同的帧保持特定的颜色会更好......可以理解,我会给变量命名。
【解决方案2】:

类似的问题已经在SO上描述过:How to have the object not revert to its initial position after animation has run?问题是在动画开始的时候,对象又回到了原来的状态。但我以不同的方式解决了这个问题:我只是将两个动画合并为一个,现在两个反转都由一个函数描述。如果您确实需要两个动画,请重做它,如我给出的链接中所述。这是我的代码:

#loader {
  width: 240px;
  height: 100px;
}

.inner {
  position: relative;
  width: 100%;
  height: 100%;
  text-align: center;
  transition: transform 2s;
  transform-style: preserve-3d;
  background-color: transparent;
}

.front,
.back {
  position: absolute;
  width: 80px;
  height: 50px;
  backface-visibility: hidden;
}

#loader1 {
  float: left;
  width: 80px;
  height: 50px;
  perspective: 1000px;
  background-color: transparent;
}

#loader1 .inner {
  animation: spin 20s ease 0s infinite;
  -webkit-animation: spin 20s ease 0s infinite;
}

#loader1 .front {
  background-color: #db9834;
}

#loader1 .back {
  background-color: #3498db;
  transform: rotateY(180deg);
}

/* -------------------------------------------------------- */

#loader2 {
  float: left;
  width: 80px;
  height: 50px;
  perspective: 1000px;
  background-color: transparent;
}

#loader2 .inner {
  animation: spin 20s ease 1s infinite;
  -webkit-animation: spin 20s ease 1s infinite;
}

#loader2 .front {
  background-color: #db8834;
}

#loader2 .back {
  background-color: #3488db;
  transform: rotateY(180deg);
}


/* -------------------------------------------------------- */

#loader3 {
  float: left;
  width: 80px;
  height: 50px;
  perspective: 1000px;
  background-color: transparent;
}

#loader3 .inner {
  animation: spin 20s ease 2s infinite;
  -webkit-animation: spin 20s ease 2s infinite;
}

#loader3 .front {
  background-color: #db7834;
}

#loader3 .back {
  background-color: #3478db;
  transform: rotateY(180deg);
}


/* -------------------------------------------------------- */

#loader4 {
  float: left;
  width: 80px;
  height: 50px;
  perspective: 1000px;
  background-color: transparent;
}

#loader4 .inner {
  animation: spin 20s ease 3s infinite;
  -webkit-animation: spin 20s ease 3s infinite;
}

#loader4 .front {
  background-color: #db6834;
}

#loader4 .back {
  background-color: #3468db;
  transform: rotateY(180deg);
}


/* -------------------------------------------------------- */

#loader5 {
  float: left;
  width: 80px;
  height: 50px;
  perspective: 1000px;
  background-color: transparent;
}

#loader5 .inner{ 
  animation: spin 20s ease 4s infinite;
  -webkit-animation: spin 20s ease 4s infinite;
}

#loader5 .front {
  background-color: #db5834;
}

#loader5 .back {
  background-color: #3458db;
  transform: rotateY(180deg);
}


/* -------------------------------------------------------- */

#loader6 {
  float: left;
  width: 80px;
  height: 50px;
  perspective: 1000px;
  background-color: transparent;
}

#loader6 .inner {
  animation: spin 20s ease 5s infinite;
  -webkit-animation: spin 20s ease 5s infinite;
}

#loader6 .front {
  background-color: #db4834;
}

#loader6 .back {
  background-color: #3448db;
  transform: rotateY(180deg);
}


@-webkit-keyframes spin {
  0% {
    -webkit-transform: rotateY(0deg);
  }
  8% {
    -webkit-transform: rotateY(180deg);
  }
  50% {
    -webkit-transform: rotateY(180deg);
  }
  
  58% {
    -webkit-transform: rotateY(0deg);
  }
  
  100% {
    -webkit-transform: rotateY(0deg);
  }
}

@keyframes spin {
  0% {
    -webkit-transform: rotateY(0deg);
  }
  8% {
    -webkit-transform: rotateY(180deg);
  }
  50% {
    -webkit-transform: rotateY(180deg);
  }
  
  58% {
    -webkit-transform: rotateY(0deg);
  }
  
  100% {
    -webkit-transform: rotateY(0deg);
  }
}
<div id="loader">
  <div id="loader1">
    <div class="inner">
      <div class="front">
      </div>
      <div class="back"> </div>
    </div>
  </div>
  <div id="loader2">
    <div class="inner">
      <div class="front"> </div>
      <div class="back"> </div>
    </div>
  </div>
  <div id="loader3">
    <div class="inner">
      <div class="front"> </div>
      <div class="back"> </div>
    </div>
  </div>
  <div id="loader4">
    <div class="inner">
      <div class="front"> </div>
      <div class="back"> </div>
    </div>
  </div>
  <div id="loader5">
    <div class="inner">
      <div class="front"> </div>
      <div class="back"> </div>
    </div>
  </div>
  <div id="loader6">
    <div class="inner">
      <div class="front"> </div>
      <div class="back"> </div>
    </div>
  </div>
</div>

【讨论】:

  • 它仍然在循环中被破坏,在完成整个动画并重新开始后,颜色开始错误地移动,并在下一个循环中再次修复。我仍然不知道由此引起的问题,但是我很努力。完成这项工作,达到一个水平。
猜你喜欢
  • 2022-01-05
  • 2022-08-13
  • 1970-01-01
  • 2016-10-30
  • 2015-01-29
  • 2012-04-26
  • 1970-01-01
相关资源
最近更新 更多