JavaScript翻转计数器

19

我想在我的网站上添加一个翻转计数器,类似于苹果在其10亿应用下载量倒计时促销中使用的那种。

输入图像描述

有人能让他们的JavaScript单独工作吗?

如果有人能提供有效的代码,那就太好了。


忘掉JS——你要窃取他们华丽的“翻转”背景图片,还是自己画一个? - Shog9
我不太了解JS,无法自己编写代码,所以才会提出这个问题。 - TeddyWilliams898
你打算用它来展示你的页面有多少访问者吗? :p - Marius
1
@Steve,太遗憾了,我之前没有看到你的评论。当我修改问题时,链接的旧的10亿应用程序倒计时只是一个静态页面,而更近期的100亿歌曲倒计时仍在实际计数。即使今天,100亿歌曲倒计时仍然是动态的,尽管倒计时已经结束,倒计时脚本只会向您显示一些带有图像的结果页面。因此,即使今天,我认为http://www.apple.com/itunes/10-billion-song-countdown/是一个更好的例子(并且在过去几周中更有可能被搜索),而不是静态的旧链接。 - Arjan
请参见http://cnanney.com/journal/code/apple-style-counter/(我与其无任何关系)。 - Arjan
5个回答

25
他们使用了CSS和JavaScript的组合。翻转动画是通过类似于CSS Sprite技术的方式实现的。
首先,他们有一个非常高的名叫filmstrip.png的图像,其中包含每个数字(0到9)的每个翻转“状态”(请看缩小的细节,您会明白我的意思)。
然后,在HTML中,每个数字由三个嵌套元素组成:
- 第一个是容器元素,它的widthheight设置为单个翻转“状态”的尺寸,其overflow设置为hidden。该元素相对定位。 - 第二个元素是绝对定位的(因为第一个元素是相对定位的,所以第二个元素是相对于第一个元素绝对定位的)。 - 第三个元素的background-image设置为filmstrip.pngwidthheight设置为该图像的尺寸。
然后,JavaScript似乎迅速更改第二个元素的top属性,导致filmstrip.png的不同部分依次显示,从而实现翻转动画。
史蒂夫

8
不,但我有Safari 4的Web Inspector工具(http://www.apple.com/safari/features.html#developer)... - Steve Harrison

24

嘿,你有创建类似背景图片的方法吗?我可以找到很多具有类似设计的免费资源,但很难制作出"翻转"效果。 - Jake

1
我已经制作了一个计数器,只需极少量的Javascript即可使其运作良好,并赋予它一些"智能":

enter image description here

function Counter(selector, settings){
  this.settings = Object.assign({
    digits: 5,
    delay: 250, // ms
    direction: ''  // ltr is default
  }, settings||{})
  
  var scopeElm = document.querySelector(selector)
  
  // generate digits markup
  var digitsHTML = Array(this.settings.digits + 1).join('<div><b data-value="0"></b></div>')
  scopeElm.innerHTML = digitsHTML;

  this.DOM = {
    scope : scopeElm,
    digits : scopeElm.querySelectorAll('b')
  }
  
  this.DOM.scope.addEventListener('transitionend', e => {
    if (e.pseudoElement === "::before" && e.propertyName == 'margin-top'){
      e.target.classList.remove('blur')
    }
  })
  
  this.count()
}

Counter.prototype.count = function(newVal){
  var countTo, className, 
      settings = this.settings,
      digitsElms = this.DOM.digits;
  
  // update instance's value
  this.value = newVal || this.DOM.scope.dataset.value|0

  if( !this.value ) return;
  
  // convert value into an array of numbers
  countTo = (this.value+'').split('')
  
  if(settings.direction == 'rtl'){
    countTo = countTo.reverse()
    digitsElms = [].slice.call(digitsElms).reverse()
  }
  
  // loop on each number element and change it
  digitsElms.forEach(function(item, i){ 
      if( +item.dataset.value != countTo[i]  &&  countTo[i] >= 0 )
        setTimeout(function(j){
            var diff = Math.abs(countTo[j] - +item.dataset.value);
            item.dataset.value = countTo[j]
            if( diff > 3 )
              item.className = 'blur';
        }, i * settings.delay, i)
  })
}



/////////////// create new counter for this demo ///////////////////////

var counter = new Counter('.numCounter', {direction:'rtl', delay:200, digits:7})
setInterval(randomCount, 3000)

function randomCount(){
  counter.count( getRandomNum(0, 9999999))
}

function getRandomNum(min,max){
    return Math.floor(Math.random()*(max-min+1) + min)
}
.numCounter {
  display: inline-block;
  height: 90px;
  line-height: 90px;
  text-shadow: 0 0 2px #fff;
  font-weight: bold;
  white-space: normal;
  font-size: 50px;
}

.numCounter > div {
  display: inline-block;
  vertical-align: top;
  height: 100%;
}

.numCounter > div > b {
  display: inline-block;
  width: 40px;
  height: 100%;
  margin: 0 0.1em;
  border-radius: 8px;
  text-align: center;
  background: white;
  overflow: hidden;
}

.numCounter > div > b::before {
  content: ' 0 1 2 3 4 5 6 7 8 9 ';
  display: block;
  word-break: break-all;
  -webkit-transition: 0.5s cubic-bezier(0.75, 0.15, 0.6, 1.15), text-shadow 150ms;
  transition: 0.5s cubic-bezier(0.75, 0.15, 0.6, 1.15), text-shadow 150ms;
}

.numCounter > div > b.blur {
  text-shadow: 2px 1px 3px rgba(0, 0, 0, 0.2), 
               0 0.1em 2px rgba(255, 255, 255, 0.6), 
               0 0.3em 3px rgba(255, 255, 255, 0.3), 
               0 -0.1em 2px rgba(255, 255, 255, 0.6), 
               0 -0.3em 3px rgba(255, 255, 255, 0.3);
}

.numCounter > div > b[data-value="1"]::before { margin-top: -90px; }
.numCounter > div > b[data-value="2"]::before { margin-top: -180px;}
.numCounter > div > b[data-value="3"]::before { margin-top: -270px;}
.numCounter > div > b[data-value="4"]::before { margin-top: -360px;}
.numCounter > div > b[data-value="5"]::before { margin-top: -450px;}
.numCounter > div > b[data-value="6"]::before { margin-top: -540px;}
.numCounter > div > b[data-value="7"]::before { margin-top: -630px;}
.numCounter > div > b[data-value="8"]::before { margin-top: -720px;}
.numCounter > div > b[data-value="9"]::before { margin-top: -810px;}

.numCounter > div:nth-last-child(3n)::before {
  content: ",";
  display: inline;
  font-size: 1.1em;
  opacity: .6;
  color: white;
}

html, body {
  height: 100%;
}

body {
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: Arial;
}

.numCounter {
  overflow: hidden;
  padding: .4em;
  text-align: center;
 
  border-radius: 16px;
  background: black;
}
.numCounter b {
  color: black;
}
<div class='numCounter' data-value='1839471'></div>

它看起来很棒,表现非常出色,并且可以从任何数字计数到任何数字。


0

在寻找同样的东西时,我发现了一个商业产品,提供了这个功能:Sprite Countdown Flip

注意:我与这个产品没有任何关联,但它做得很好,可能对某些人有用。


0

我推荐使用开源版本:FlipclockJS,这个版本很可能是在这个事件之后创建的 :)

Github: objectivehtml/FlipClock,可通过NPM和Bower获取(未维护)


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