CSS动画重复中的延迟

109

我最近发现了如何“正确地”使用CSS动画(之前我认为它们无法制作像JavaScript一样的复杂序列,所以对它们不屑一顾)。所以现在我正在学习它们。

对于这个效果,我想让一个渐变色“闪烁”扫过一个类似进度条的元素,就像原生Windows Vista/7进度条上的效果。

@keyframes barshine {
  from {background-image:linear-gradient(120deg,rgba(255,255,255,0) -10%,rgba(255,255,255,0.25) -5%,rgba(255,255,255,0) 0%);}
  to {background-image:linear-gradient(120deg,rgba(255,255,255,0) 100%,rgba(255,255,255,0.25) 105%,rgba(255,255,255,0) 110%);}
}
.progbar {
  animation: barshine 1s 4s linear infinite;
}

如您所见,我正在尝试延迟4秒后,在1秒内扫过的闪光,不断重复。

然而,看起来animation-delay仅适用于第一次迭代,之后闪光将不断重复扫过。

我通过以下方式“解决”了这个问题:

@keyframes expbarshine {
  from {background-image:linear-gradient(120deg,rgba(255,255,255,0) -10%,rgba(255,255,255,0.25) -5%,rgba(255,255,255,0) 0%);}
  80% {background-image:linear-gradient(120deg,rgba(255,255,255,0) -10%,rgba(255,255,255,0.25) -5%,rgba(255,255,255,0) 0%);}
  to {background-image:linear-gradient(120deg,rgba(255,255,255,0) 100%,rgba(255,255,255,0.25) 105%,rgba(255,255,255,0) 110%);}
}
.progbar {
  animation: barshine 5s linear infinite;
}

from80%是完全相同的,导致动画长度的80%的“延迟”。

这种方法可行,但对于我的下一个动画,我需要延迟是可变的(对于特定元素是恒定的,但针对使用该动画的不同元素是可变的),而动画本身的长度保持完全相同。

通过上述“解决方案”,当我想要更长的延迟时间时,我最终会得到一个更慢的动画。

是否可以让animation-delay应用于所有迭代,而不仅仅是第一个迭代?


1
很遗憾,没有其他类似于animation-delay的属性。animation-delay是动画开始前的延迟时间。虽然有一种使用JavaScript的不好的解决方法,但您可能不想使用它 :) - Ry-
12个回答

73

我遇到过类似的问题,我使用了

@-webkit-keyframes pan {
   0%, 10%       { -webkit-transform: translate3d( 0%, 0px, 0px); }
   90%, 100%     { -webkit-transform: translate3d(-50%, 0px, 0px); }
}

有点恼人的是你必须伪造你的时长来考虑两端的“延迟”。


25

minitech是正确的,animation-delay指定的是动画开始之前的延迟时间,而不是迭代之间的延迟时间。 规范的编辑草案对此进行了描述,并且有关此功能的讨论在这里建议使用这个迭代延迟功能。

虽然可以通过JS解决问题,但您可以仅使用CSS来模拟进度条闪烁的迭代延迟。

通过声明闪烁div的position:absolute和父div的overflow:hidden,将100%关键帧状态设置为大于进度条宽度,并尝试使用贝塞尔曲线计时函数和左偏移值,可以模拟具有“延迟”的ease-in-outlinear计时。

编写一个 less/scss mixin 以计算确切的左偏移值和计时函数来获得这个效果将非常有趣,但我暂时没有时间去调整它。不过我很想看到这样的东西!

这里是我准备好的演示。 (我尝试模拟了Windows 7的进度条,但有些不足,但它展示了我所说的内容)

演示: http://codepen.io/timothyasp/full/HlzGu

<!-- HTML -->
<div class="bar">
   <div class="progress">
      <div class="flare"></div>
   </div>
</div>


/* CSS */

@keyframes progress {
  from {
    width: 0px;
  }
  to {
    width: 600px;
  }
}

@keyframes barshine {
  0% {
    left: -100px;
  }

  100% {
    left: 1000px;
  }
}
.flare {
  animation-name: barshine;
  animation-duration: 3s;
  animation-direction: normal;
  animation-fill-mode: forwards;
  animation-timing-function: cubic-bezier(.14, .75, .2, 1.01);
  animation-iteration-count: infinite;
  left: 0;
  top: 0;
  height: 40px;
  width: 100px;
  position: absolute;
  background: -moz-radial-gradient(center, ellipse cover,  rgba(255,255,255,0.69) 0%, rgba(255,255,255,0) 87%); /* FF3.6+ */
  background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%,rgba(255,255,255,0.69)), color-stop(87%,rgba(255,255,255,0))); /* Chrome,Safari4+ */
  background: -webkit-radial-gradient(center, ellipse cover,  rgba(255,255,255,0.69) 0%,rgba(255,255,255,0) 87%); /* Chrome10+,Safari5.1+ */
  background: -o-radial-gradient(center, ellipse cover,  rgba(255,255,255,0.69) 0%,rgba(255,255,255,0) 87%); /* Opera 12+ */
  background: -ms-radial-gradient(center, ellipse cover,  rgba(255,255,255,0.69) 0%,rgba(255,255,255,0) 87%); /* IE10+ */
  background: radial-gradient(ellipse at center,  rgba(255,255,255,0.69) 0%,rgba(255,255,255,0) 87%); /* W3C */
  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#b0ffffff', endColorstr='#00ffffff',GradientType=1 ); /* IE6-9 fallback on horizontal gradient */
  z-index: 10;
}
.progress {
  animation-name: progress;
  animation-duration: 10s;
  animation-delay: 1s;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
  overflow: hidden;
  position:relative;
  z-index: 1;
  height: 100%;
  width: 100%;
  border-right: 1px solid #0f9116;
  background: #caf7ce; /* Old browsers */
  background: -moz-linear-gradient(top, #caf7ce 0%, #caf7ce 18%, #3fe81e 45%, #2ab22a 96%); /* FF3.6+ */
  background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#caf7ce), color-stop(18%,#caf7ce), color-stop(45%,#3fe81e), color-stop(96%,#2ab22a)); /* Chrome,Safari4+ */
  background: -webkit-linear-gradient(top, #caf7ce 0%,#caf7ce 18%,#3fe81e 45%,#2ab22a 96%); /* Chrome10+,Safari5.1+ */
  background: -o-linear-gradient(top, #caf7ce 0%,#caf7ce 18%,#3fe81e 45%,#2ab22a 96%); /* Opera 11.10+ */
  background: -ms-linear-gradient(top, #caf7ce 0%,#caf7ce 18%,#3fe81e 45%,#2ab22a 96%); /* IE10+ */
  background: linear-gradient(to bottom, #caf7ce 0%,#caf7ce 18%,#3fe81e 45%,#2ab22a 96%); /* W3C */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#caf7ce', endColorstr='#2ab22a',GradientType=0 ); /* IE6-9 */
}

.progress:after {
  content: "";
  width: 100%;
  height: 29px;
  right: 0;
  bottom: 0;
  position: absolute;
  z-index: 3;
  background: -moz-linear-gradient(left, rgba(202,247,206,0) 0%, rgba(42,178,42,1) 100%); /* FF3.6+ */
  background: -webkit-gradient(linear, left top, right top, color-stop(0%,rgba(202,247,206,0)), color-stop(100%,rgba(42,178,42,1))); /* Chrome,Safari4+ */
  background: -webkit-linear-gradient(left, rgba(202,247,206,0) 0%,rgba(42,178,42,1) 100%); /* Chrome10+,Safari5.1+ */
  background: -o-linear-gradient(left, rgba(202,247,206,0) 0%,rgba(42,178,42,1) 100%); /* Opera 11.10+ */
  background: -ms-linear-gradient(left, rgba(202,247,206,0) 0%,rgba(42,178,42,1) 100%); /* IE10+ */
  background: linear-gradient(to right, rgba(202,247,206,0) 0%,rgba(42,178,42,1) 100%); /* W3C */
  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00caf7ce', endColorstr='#2ab22a',GradientType=1 ); /* IE6-9 */
}

.bar {
  margin-top: 30px;
  height: 40px;
  width: 600px;
  position: relative;
  border: 1px solid #777;
  border-radius: 3px;
}

70
典型的CSS。它们提供CSS动画,因此不需要使用Javascript,并且样式都在一个地方,但是如果你想做比基本操作更多的事情,那么就必须实现一系列的hack。为什么他们不直接实现使开发者更容易的东西呢? - Jonathan.

20

你可以通过应用第二个动画来隐藏元素的方式,在动画之间实现暂停。这种方法的好处是可以像往常一样使用CSS缓动函数。

.star {
  animation: shooting-star 1000ms ease-in-out infinite,
    delay-animation 2000ms linear infinite;
}

@keyframes shooting-star {
  0% {
    transform: translate(0, 0) rotate(45deg);
  }

  100% {
    transform: translate(300px, 300px) rotate(45deg);
  }
}

@keyframes delay-animation {
  0% {
    opacity: 1;
  }
  50% {
    opacity: 1;
  }
  50.01% {
    opacity: 0;
  }
  100% {
    opacity: 0;
  }
}

只有当您希望延迟是动画持续时间的倍数时,此方法才有效。我使用这种方法使一场流星雨看起来更加随机: https://codepen.io/ericdjohnson/pen/GRpOgVO


这真是聪明绝顶。 - LandonSchropp

12

这是您应该做的。它应该能够正常工作,因为您有1秒的动画时间,然后在每次迭代之间有4秒的延迟:

@keyframes barshine {
  0% {
  background-image:linear-gradient(120deg,rgba(255,255,255,0) 0%,rgba(255,255,255,0.25) -5%,rgba(255,255,255,0) 0%);
  }
  20% {
    background-image:linear-gradient(120deg,rgba(255,255,255,0) 10%,rgba(255,255,255,0.25) 105%,rgba(255,255,255,0) 110%);
  }
}
.progbar {
  animation: barshine 5s 0s linear infinite;
}

我一直在尝试这个,你可以不用太过“hacky”(指不正式或非官方的)来实现。这是在动画迭代之间放置延迟的最简单方法,1. 非常容易,2. 只需要一点逻辑。看看我制作的这个舞蹈动画:

.dance{
  animation-name: dance;
  -webkit-animation-name: dance;

  animation-iteration-count: infinite;
  -webkit-animation-iteration-count: infinite;
  animation-duration: 2.5s;
  -webkit-animation-duration: 2.5s;

  -webkit-animation-delay: 2.5s;
  animation-delay: 2.5s;
  animation-timing-function: ease-in;
  -webkit-animation-timing-function: ease-in;

}
@keyframes dance {
  0% {
    -webkit-transform: rotate(0deg);
    -moz-transform: rotate(0deg);
    -o-transform: rotate(0deg);
    -ms-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  25% {
    -webkit-transform: rotate(-120deg);
    -moz-transform: rotate(-120deg);
    -o-transform: rotate(-120deg);
    -ms-transform: rotate(-120deg);
    transform: rotate(-120deg);
  }
  50% {
    -webkit-transform: rotate(20deg);
    -moz-transform: rotate(20deg);
    -o-transform: rotate(20deg);
    -ms-transform: rotate(20deg);
    transform: rotate(20deg);
  }
  100% {
    -webkit-transform: rotate(0deg);
    -moz-transform: rotate(0deg);
    -o-transform: rotate(0deg);
    -ms-transform: rotate(0deg);
    transform: rotate(0deg);
  }
}

@-webkit-keyframes dance {
  0% {
    -webkit-transform: rotate(0deg);
    -moz-transform: rotate(0deg);
    -o-transform: rotate(0deg);
    -ms-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  20% {
    -webkit-transform: rotate(20deg);
    -moz-transform: rotate(20deg);
    -o-transform: rotate(20deg);
    -ms-transform: rotate(20deg);
    transform: rotate(20deg);
  }
  40% {
    -webkit-transform: rotate(-120deg);
    -moz-transform: rotate(-120deg);
    -o-transform: rotate(-120deg);
    -ms-transform: rotate(-120deg);
    transform: rotate(-120deg);
  }
  60% {
    -webkit-transform: rotate(0deg);
    -moz-transform: rotate(0deg);
    -o-transform: rotate(0deg);
    -ms-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  80% {
    -webkit-transform: rotate(-120deg);
    -moz-transform: rotate(-120deg);
    -o-transform: rotate(-120deg);
    -ms-transform: rotate(-120deg);
    transform: rotate(-120deg);
  }
  95% {
    -webkit-transform: rotate(20deg);
    -moz-transform: rotate(20deg);
    -o-transform: rotate(20deg);
    -ms-transform: rotate(20deg);
    transform: rotate(20deg);
  }
}

我实际上来到这里是想找出如何在动画中添加延迟,后来发现你只需要1.延长动画的持续时间并缩短每个动画的时间比例。以前,我让它们每个持续0.5秒,总持续时间为2.5秒。现在假设我想添加一个等于总持续时间的延迟,即2.5秒。

你的动画时间是2.5秒,延迟是2.5秒,所以你需要将持续时间更改为5秒。但是,由于你加倍了总持续时间,所以你需要将动画的比例减半。查看下面的最终结果。对我来说,这很完美地起作用。

@-webkit-keyframes dance {
  0% {
    -webkit-transform: rotate(0deg);
    -moz-transform: rotate(0deg);
    -o-transform: rotate(0deg);
    -ms-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  10% {
    -webkit-transform: rotate(20deg);
    -moz-transform: rotate(20deg);
    -o-transform: rotate(20deg);
    -ms-transform: rotate(20deg);
    transform: rotate(20deg);
  }
  20% {
    -webkit-transform: rotate(-120deg);
    -moz-transform: rotate(-120deg);
    -o-transform: rotate(-120deg);
    -ms-transform: rotate(-120deg);
    transform: rotate(-120deg);
  }
  30% {
    -webkit-transform: rotate(0deg);
    -moz-transform: rotate(0deg);
    -o-transform: rotate(0deg);
    -ms-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  40% {
    -webkit-transform: rotate(-120deg);
    -moz-transform: rotate(-120deg);
    -o-transform: rotate(-120deg);
    -ms-transform: rotate(-120deg);
    transform: rotate(-120deg);
  }
  50% {
    -webkit-transform: rotate(0deg);
    -moz-transform: rotate(0deg);
    -o-transform: rotate(0deg);
    -ms-transform: rotate(0deg);
    transform: rotate(0deg);
  }
}

简而言之:

这些是您可能会使用的计算方法,以确定如何更改动画的持续时间和每个部分的百分比。

desired_duration = x

desired_duration = animation_part_duration1 + animation_part_duration2 + ...(等等)

desired_delay = y

total duration = x + y

animation_part_duration1_actual = animation_part_duration1 * desired_duration / total_duration


法国人发现了 :) (我也是法国人,别担心) - julesbou

6

我宁愿写一点JavaScript,也不想让CSS变得难以管理。

首先,仅在数据属性更改时应用CSS动画:

.progbar[data-animation="barshine"] {
    animation: barshine 1s linear;
}

然后加入 JavaScript 以在延迟时间的一半切换动画。
var progbar = document.querySelector('.progbar');
var on = false;

setInterval(function () {
    progbar.setAttribute('data-animation', (on) ? 'barshine' : '');
    on = !on;
}, 3000);

如果您不希望在选项卡隐藏时运行动画:
var progbar = document.querySelector('.progbar');
var on = false;

var update = function () {
    progbar.setAttribute('data-animation', (on) ? 'barshine' : '');
    on = !on;
    setTimer();
};

var setTimer = function () {
    setTimeout(function () {
        requestAnimationFrame(update);
    }, 3000);
};

setTimer();

3
我在墙上做了一个海报,它会左右移动并间隔一段时间。对我而言,这很有效:
.div-animation {
   -webkit-animation: bounce 2000ms ease-out;
    -moz-animation: bounce 2000ms ease-out;
    -o-animation: bounce 2000ms ease-out;
    animation: bounce 2000ms ease-out infinite;
    -webkit-animation-delay: 2s; /* Chrome, Safari, Opera */
    animation-delay: 2s;
    transform-origin: 55% 10%;    
}

@-webkit-keyframes bounce {
    0% {
        transform: rotate(0deg);
    }
    3% {
        transform: rotate(1deg);
    }
    6% {
        transform: rotate(2deg);
    }
    9% {
        transform: rotate(3deg);
    }
    12% {
        transform: rotate(2deg);
    }
    15% {
        transform: rotate(1deg);
    }
    18% {
        transform: rotate(0deg);
    }
    21% {
        transform: rotate(-1deg);
    }
    24% {
        transform: rotate(-2deg);
    }
    27% {
        transform: rotate(-3deg);
    }
    30% {
        transform: rotate(-2deg);
    }
    33% {
        transform: rotate(-1deg);
    }
    36% {
        transform: rotate(0deg);
    }
    100% {
        transform: rotate(0deg);
    }
}

2
这是一个小片段,它展示了75%的时间相同的事情,然后滑动。这个重复模式很好地模拟了延迟:
@-webkit-keyframes slide    {
0%   {background-position: 0 0;}
25%  {background-position: 0 0;}
50%  {background-position: 0 0;}
75%  {background-position: 0 0;}
100% {background-position: 13em 0;}
}

@-moz-keyframes slide       {
0%   {background-position: 0 0;}
25%  {background-position: 0 0;}
50%  {background-position: 0 0;}
75%  {background-position: 0 0;}
100% {background-position: 13em 0;}
}

@keyframes slide            {
0%   {background-position: 0 0;}
25%  {background-position: 0 0;}
50%  {background-position: 0 0;}
75%  {background-position: 0 0;}
100% {background-position: 13em 0;}
}

1

对于边框闪烁效果: 实际上非常简单:将“from”替换为“to”,将“to”替换为99%的黑色和1%的蓝色位移。 您甚至可以将动画时间设置更短,例如5秒。

@keyframes myborder {
  0% {border-color: black;}
  99% {border-color:black;}
  100% {border-color: blue;}
 }

1
你可以通过纯CSS创建“假”延迟以在无限动画之间添加间隔。方法是聪明地定义关键帧动画点和动画持续时间速度。
例如,如果我们想要动画一个弹跳的球,并且我们希望每次弹跳之间有0.5秒到1秒的良好延迟,我们可以这样做:
@keyframes bounce{
    0%{
        transform: translateY(0);
    }
    50%{
        transform: translateY(25%);
    }
    75%{
        transform: translateY(15%);
    }
    90%{
        transform: translateY(0%);
    }
    100%{
        transform: translateY(0);
    }
}

我们所做的是确保球在比100%更早的时间回到其原始位置。在我的例子中,我将它设为90%,这给了我大约0.1秒的延迟,对我来说已经足够好了。但显然对于你的情况,你可以添加更多的关键帧点并更改变换值。
此外,您可以添加额外的动画持续时间来平衡关键帧动画。
例如:
 animation: bounce .5s ease-in-out infinite;

假设我们希望完整的动画在0.5秒内结束,但我们希望在动画之间增加额外的0.2秒延迟。
 animation: bounce .7s ease-in-out infinite;

所以我们将增加额外的.2秒延迟,在我们的关键帧动画中,我们可以添加更多的百分比点来填补.2秒延迟的空白。

我通常会这样做。缺点是,如果要调整动画,就会变得非常困难,因为每次时间的更改都需要更改所有值。除非你使用大量的Sass变量来正确设置它,但这通常需要太多的努力。 - Beppe

0

延迟只能在无限循环的开始时使用一次。 换句话说,延迟不能与无限循环一起使用。 为此,您必须保持关键帧动画为空白,例如:

@-webkit-keyframes barshine {
  10% {background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#1e5799), color-stop(100%,#7db9e8));
    }
  60% {background: -webkit-linear-gradient(top, #7db9e8 0%,#d32a2d 100%);}
}

它将从10%动画到60%,并等待完成40%。 因此,40%会延迟。

查找小提琴示例


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接