【问题标题】:CSS animation delay in repeatingCSS动画延迟重复
【发布时间】:2012-12-02 23:57:22
【问题描述】:

我最近发现了如何“正确”使用 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 应用于所有迭代,而不仅仅是第一次?

【问题讨论】:

  • 不幸的是,没有。 animation-delay 是动画开始前的延迟,没有其他类似的属性。 JavaScript 有一个不好的解决方法,您可能不想使用它:)

标签: css css-animations


【解决方案1】:

我也遇到过类似的问题,用过

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

有点恼人的是,你必须伪造你的持续时间来解释两端的“延迟”。

【讨论】:

    【解决方案2】:

    minitech 是正确的,animation-delay 指定了动画开始之前的延迟,而 NOT 指定了迭代之间的延迟。 The editors draft of the spec 很好地描述了它,并且有一个关于你描述的这个特性的讨论 here 这暗示了这个迭代延迟特性。

    虽然在 JS 中可能有一种解决方法,但您可以仅使用 CSS 来伪造进度条耀斑的迭代延迟。

    通过声明flare div position:absolute 和父div overflow: hidden,将100% 关键帧状态设置为大于进度条的宽度,以及playing around with the cubic-bezier timing function 和左偏移值,您可以模拟一个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;
    }
    

    【讨论】:

    • 典型的 CSS。他们提供 CSS 动画,所以它不是在 Javascript 中完成的,并且样式都在一个地方,但是如果你想做的不仅仅是基本的基础,那么你必须实现一个 hack 的迷宫。他们为什么不直接实现让开发人员更容易的东西?
    【解决方案3】:

    这是你应该做的。它的工作原理是你有一个 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;
    }
    

    所以我一直在搞砸这件事,而你可以做到这一点而不会很笨拙。这是在动画迭代之间设置延迟的最简单方法,即 1. SUPER EASY 和 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. 延长动画的持续时间和衬衫每个动画的时间比例。 Beore 我让它们每个持续 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

    总持续时间 = x + y

    animation_part_duration1_actual = animation_part_duration1 * desired_duration / total_duration

    【讨论】:

    • 发现法国人 :)(我也是法国人,别担心)
    【解决方案4】:

    实现动画之间暂停的另一种方法是应用第二个动画,该动画将元素隐藏到所需的延迟量。这样做的好处是允许您像往常一样使用 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

    【讨论】:

    • 这真是太聪明了。
    【解决方案5】:

    我宁愿写一点 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();
    

    【讨论】:

      【解决方案6】:

      这是一个小 sn-p,它在 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;}
      }
      

      【讨论】:

        【解决方案7】:

        我在墙上做了一张海报,它有间隔地左右移动。对我来说它有效:

        .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);
            }
        }
        

        【讨论】:

          【解决方案8】:

          您可以纯粹使用 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;
          

          所以我们会增加一个额外的 .2s 延迟,并且在我们的关键帧动画中,我们可以添加更多的百分比来填补 .2s 延迟的空白。

          【讨论】:

          • 我通常会这样做。不利的一面是,调整动画变得非常困难,因为时间的每次变化都需要更改所有值。除非你用大量的 sass 变量正确设置它,这通常是太多的努力。
          【解决方案9】:

          对于边框闪光: 实际上非常简单:将黑色替换为 99%,例如 1% 变为蓝色 您甚至可以将其缩短,将动画时间设置为例如 5 秒。

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

          【讨论】:

            【解决方案10】:

            延迟只能在开始时无限次。 排序延迟不适用于无限循环。 为此,您必须保留关键帧动画空白示例:

            @-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% 延迟到来。

            find fiddle example

            【讨论】:

              【解决方案11】:

              我知道这已经过时了,但我一直在这篇文章中寻找答案,而使用 jquery,您可以轻松地做到这一点,而且没有太多麻烦。只需在 css 中声明您的动画关键帧并使用您想要的属性设置类。在我的情况下,我使用了 css animate 中的 tada 动画:

              .tada {
                  -webkit-animation-name: tada;
                  animation-name: tada;
                  -webkit-animation-duration: 1.25s;
                  animation-duration: 1.25s;
                  -webkit-animation-fill-mode: both;
                  animation-fill-mode: both;
              }
              

              我希望动画每 10 秒运行一次,所以 jquery 只是添加了类,在 6000 毫秒(动画完成的足够时间)之后,它删除了类,4 秒后它再次添加了类,所以动画再次开始。

              $(document).ready(function() {
                setInterval(function() {
              
                  $(".bottom h2").addClass("tada");//adds the class
              
                  setTimeout(function() {//waits 6 seconds to remove the class
                    $(".bottom h2").removeClass("tada");
                  }, 6000);
              
                }, 10000)//repeats the process every 10 seconds
              });
              

              一点也不像一个人说的那么难。

              【讨论】:

              • 我不知道你为什么要为.classList.add("tada") 使用jQuery :D
              • 我猜它更容易记住......而且你根本不需要使用 jquery,如果你愿意,你可以编写 3 行 javascript 行,而不是只用 jquery 编写 1 行,这完全取决于编写代码的人:)
              • 我不知道,$(".bottom h2").addClass("tada")document.querySelector(".bottom h2").classList.add("tada") 如此相似以至于不值得加载/运行 jQuery 代码的开销:p
              • 我猜你是对的。我在使用 javascript 的免费前端看到了这个非常酷的滑块,因为我主要使用 jquery,所以我尝试用它来复制滑块,我这样做了,但它需要的资源是使用 javascript 制作的原始滑块的 5 倍 :( 我猜javascript 比使用 jquery 代码更轻量级,另一方面它不那么冗长
              猜你喜欢
              • 2019-08-15
              • 2019-05-31
              • 1970-01-01
              • 2017-12-04
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多