【问题标题】:CSS Animation: Number increment effectCSS动画:数字递增效果
【发布时间】:2015-03-13 10:48:15
【问题描述】:

我想在数字快速变化时获得那种动画效果,例如:http://jsbin.com/kevalutupe/1/

我想单独编写这个 CSS(我知道如何在 JS 中编写代码),我不想使用 JS,因为我觉得锤击 DOM 并不是最好的解决方案。这完全可以用 CSS 实现吗?

我对实际正确递增的数字并不在意,我只是在追求效果。

【问题讨论】:

    标签: css animation css-animations


    【解决方案1】:

    使用 CSS3 动画绝对可以实现数字旋转效果,更好的是,您还可以使用少量 JS 设置端点并实际获得全部功能。

    方法说明:

    1. 创建了div,通过将其高度和宽度设置为1em,它始终只显示一个数字。 div 的溢出设置为隐藏,以便仅显示一行。
    2. 在这个 div 中创建了一个包含从 1 到 0 的所有数字的 span,并相对于父级进行定位。
    3. span 的初始位置为 0px 或 0em,但在 animation 期间顶部位置发生变化,因此 span 给人以向上移动的印象。因为div 一次只能显示一个数字,所以会产生旋转效果(或其他数字消失的效果)。
    4. 最终位置是通过为每个span 元素设置一个固定的顶部位置来实现的。 0em 表示第一行可见(数字 1),-2em 表示第三行可见(数字 3),依此类推。
    5. 增加或减少动画持续时间将使旋转效果快速或缓慢发生。动画迭代计数设置为 5,以产生微调器旋转多次的错觉。

    注意: 使用这种方法,旋转看起来每次都会转一圈,而不像有问题的 JSBin 示例,其中第一个数字的 3 到 4 只是一个数字一步而不是一个完整的圆圈。

    div {
      width: 1em;
      height: 1em;
      overflow: hidden;
      line-height: 1em;
      display: inline-block;
    }
    span {
      position: relative;
    }
    .animate {
      -webkit-animation: spinit 0.2s 5;
      -moz-animation: spinit 0.2s 5;
      animation: spinit 0.2s 5;
    }
    @-webkit-keyframes spinit {
      0% {
        top: 0em;
      }
      50% {
        top: -5em;
      }
      100% {
        top: -9em;
      }
    }
    @-moz-keyframes spinit {
      0% {
        top: 0em;
      }
      50% {
        top: -5em;
      }
      100% {
        top: -9em;
      }
    }
    @keyframes spinit {
      0% {
        top: 0em;
      }
      50% {
        top: -5em;
      }
      100% {
        top: -9em;
      }
    }
    
    /* Setting the required value to top will make the spinner end at that number */
    
    #digit1 {
      top: -4em;
      /* -4em means 5 will be the number */
    }
    #digit2 {
      top: -2em;
    }
    #digit3 {
      top: 0em;
    }
    <div>
      <span class="animate" id='digit1'>1 2 3 4 5 6 7 8 9 0</span>
    </div>
    <div>
      <span class="animate" id='digit2'>1 2 3 4 5 6 7 8 9 0</span>
    </div>
    <div>
      <span class="animate" id='digit3'>1 2 3 4 5 6 7 8 9 0</span>
    </div>

    下面是一个使用 JavaScript 的示例,其中动画效果是通过 CSS 实现的,但动画的触发和端点的设置是使用 JavaScript 实现的。

    JS 代码几乎是不言自明的。我们正在做的事情如下:

    1. 为按钮的单击事件创建一个侦听器,并在其中将animate 类添加到作为此动画效果一部分的所有span 元素。这是因为我们希望动画仅在单击按钮时发生。
    2. 当动画结束(或旋转完成)时,我们将每个spantop 属性设置为某个随机数。这意味着每个跨度将显示不同的数字。
    3. 在动画结束时,我们还调用另一个函数来删除animate 类,这样当我们再次单击按钮时,动画可以重新开始。

    window.onload = function() {
      var spinner = document.getElementById('spinner');
      spinner.onclick = spinit;
    
      var el = document.querySelectorAll("span[id*=digit]");
      for (i = 0; i < el.length; i++) {
        el[i].addEventListener("animationend", randomize, false);
        el[i].addEventListener("webkitAnimationEnd", randomize, false);
        el[i].addEventListener("oanimationend", randomize, false);
        el[i].addEventListener("MSAnimationEnd", randomize, false);
      }
    }
    
    function randomize() {
      var rand = Math.floor(Math.random() * 9);
      this.style.top = -1 * rand + "em";
      this.classList.toggle('animate');
    }
    
    function spinit() {
      var el = document.querySelectorAll("span[id*=digit]");
      for (i = 0; i < el.length; i++) {
        el[i].classList.toggle('animate');
      }
    }
    div {
      width: 1em;
      height: 1em;
      overflow: hidden;
      line-height: 1em;
      display: inline-block;
    }
    span {
      position: relative;
    }
    .animate {
      -webkit-animation: spinit 0.2s 5;
      -moz-animation: spinit 0.2s 5;
      animation: spinit 0.2s 5;
    }
    @-webkit-keyframes spinit {
      0% {
        top: 0em;
      }
      50% {
        top: -5em;
      }
      100% {
        top: -9em;
      }
    }
    @-moz-keyframes spinit {
      0% {
        top: 0em;
      }
      50% {
        top: -5em;
      }
      100% {
        top: -9em;
      }
    }
    @keyframes spinit {
      0% {
        top: 0em;
      }
      50% {
        top: -5em;
      }
      100% {
        top: -9em;
      }
    }
    
    /* Set the value according to the on-load position of the spinner */
    
    #digit1 {
      top: -4em;
      /* -4em means 5 will be the number */
    }
    #digit2 {
      top: -2em;
    }
    #digit3 {
      top: 0em;
    }
    <div>
      <span id='digit1'>1 2 3 4 5 6 7 8 9 0</span>
    </div>
    
    <div>
      <span id='digit2'>1 2 3 4 5 6 7 8 9 0</span>
    </div>
    
    <div>
      <span id='digit3'>1 2 3 4 5 6 7 8 9 0</span>
    </div>
    
    <button id='spinner'>Spin It</button>

    第 2 版:(仅具有数字增量效果而不是旋转效果)

    这是使用与前一个基本相同的代码创建的,但与前一个不同的是,animation 使从一个数字到另一个数字的移动是渐进的(从而产生旋转效果),这里的动画使运动更像是从一个数字突然跳到另一个数字,从而产生增量效应。

    跳跃是通过保持top 的位置不变直到它即将移动到下一个来实现的(也就是说,top 设置为0em 直到动画的 9.9%,但在 10 % 突然变成-1em)。

    window.onload = function() {
      var spinner = document.getElementById('spinner');
      spinner.onclick = spinit;
    
      var el = document.querySelectorAll("span[id*=digit]");
      for (i = 0; i < el.length; i++) {
        el[i].addEventListener("animationend", randomize, false);
        el[i].addEventListener("webkitAnimationEnd", randomize, false);
        el[i].addEventListener("oanimationend", randomize, false);
        el[i].addEventListener("MSAnimationEnd", randomize, false);
      }
    }
    
    function randomize() {
      var rand = Math.floor(Math.random() * 9);
      this.style.top = -1 * rand + "em";
      this.classList.toggle('animate');
    }
    
    function spinit() {
      var el = document.querySelectorAll("span[id*=digit]");
      for (i = 0; i < el.length; i++) {
        el[i].classList.toggle('animate');
      }
    }
    div {
      width: 1em;
      height: 1em;
      overflow: hidden;
      line-height: 1em;
      display: inline-block;
    }
    span {
      position: relative;
    }
    .animate {
      -webkit-animation: spinit 0.2s 5;
      -moz-animation: spinit 0.2s 5;
      animation: spinit 0.2s 5;
    }
    @-webkit-keyframes spinit {
      0% { top: 0em; }
      9.9% { top: 0em; }
      10%{ top: -1em; }
      19.9%{ top: -1em; }
      20%{ top: -2em; }
      29.9%{ top: -2em; }
      30%{ top: -3em; }
      39.9%{ top: -3em; }
      40%{ top: -4em; }
      49.9%{ top: -4em; }
      50% { top: -5em; }
      59.9%{ top: -5em; }
      60%{ top: -6em; }
      69.9%{ top: -6em; }
      70%{ top: -7em; }
      79.9%{ top: -7em; }
      80%{ top: -8em; }
      89.9%{ top: -8em; }
      90%{ top: -9em; }
      99.9%{ top: -9em; }
      100% { top: -9em; }
    }
    @-moz-keyframes spinit {
      0% { top: 0em; }
      9.9% { top: 0em; }
      10%{ top: -1em; }
      19.9%{ top: -1em; }
      20%{ top: -2em; }
      29.9%{ top: -2em; }
      30%{ top: -3em; }
      39.9%{ top: -3em; }
      40%{ top: -4em; }
      49.9%{ top: -4em; }
      50% { top: -5em; }
      59.9%{ top: -5em; }
      60%{ top: -6em; }
      69.9%{ top: -6em; }
      70%{ top: -7em; }
      79.9%{ top: -7em; }
      80%{ top: -8em; }
      89.9%{ top: -8em; }
      90%{ top: -9em; }
      99.9%{ top: -9em; }
      100% { top: -9em; }
    }
    @keyframes spinit {
      0% { top: 0em; }
      9.9% { top: 0em; }
      10%{ top: -1em; }
      19.9%{ top: -1em; }
      20%{ top: -2em; }
      29.9%{ top: -2em; }
      30%{ top: -3em; }
      39.9%{ top: -3em; }
      40%{ top: -4em; }
      49.9%{ top: -4em; }
      50% { top: -5em; }
      59.9%{ top: -5em; }
      60%{ top: -6em; }
      69.9%{ top: -6em; }
      70%{ top: -7em; }
      79.9%{ top: -7em; }
      80%{ top: -8em; }
      89.9%{ top: -8em; }
      90%{ top: -9em; }
      99.9%{ top: -9em; }
      100% { top: -9em; }
    }
    
    /* Set the value according to the on-load position of the spinner */
    
    #digit1 {
      top: -4em;
      /* -4em means 5 will be the number */
    }
    #digit2 {
      top: -2em;
    }
    #digit3 {
      top: 0em;
    }
    <div>
      <span id='digit1'>1 2 3 4 5 6 7 8 9 0</span>
    </div>
    
    <div>
      <span id='digit2'>1 2 3 4 5 6 7 8 9 0</span>
    </div>
    
    <div>
      <span id='digit3'>1 2 3 4 5 6 7 8 9 0</span>
    </div>
    
    <button id='spinner'>Spin It</button>

    【讨论】:

    • 玩过这个,有没有什么办法可以让旋转效果消失?我想要的只是数字在静态位置快速变化的效果。
    • @duck:我为答案伙伴添加了另一个变体。这看起来更接近您想要实现的目标。就我个人而言,我不认为使用 CSS 可以实现更多。