CSS动画:数字增量效果

18

我想要实现数字快速变化时的动画效果,例如:http://jsbin.com/kevalutupe/1/

我希望只使用CSS来实现(虽然我知道如何在JS中编写它),因为我认为不断操作DOM并不是最好的解决方案。在CSS中是否可能实现这一点?

我并不关心数字是否正确递增,我只关心产生的效果。

1个回答

40
使用CSS3动画可以实现数字旋转效果,而更好的是,您还可以使用一小段JS设置终点并实际获得其全部功能。
方法说明: 1.创建一个div,使其始终仅显示一个数字,通过将其高度和宽度设置为1em实现。将div的溢出设置为隐藏,以便只显示一行。 2.在此div中创建一个包含所有数字(从1到0)的span,并相对于父元素定位。 3. span的初始位置为0像素或0em,但在动画期间,顶部位置会改变,以便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. 当动画结束(或旋转完成)时,我们将每个 span 的 top 属性设置为某个随机数。这意味着每个 span 将显示不同的数字。 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>


第二版: (只有数字增加效果,没有旋转效果)

这个版本的代码基本上与之前的代码相同,但不同的是,之前的animation让数字从一个数值渐变到另一个数值(从而产生旋转效果),而这里的动画使数字更像是突然跳跃到另一个数字,因此只产生了一个增量效果。

跳跃的效果是通过保持top位置不变直到到了下一个数字的时间(也就是说,在动画的前9.9%,top被设置为0em,但在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>


玩了一下,有没有办法消除旋转效果?我只想要数字在静止位置快速变化的效果。 - ditto
@duck:我已经给答案添加了另一种变体,这看起来更接近你想要实现的效果。就个人而言,我认为使用CSS不可能再实现更多了。 - Harry

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