Счетчик переворотов JavaScript

Я хотел бы разместить на своем сайте флип-счетчик, аналогичный тому, что Apple использовала для своего обратный отсчет до 1 миллиарда приложений.

введите здесь описание изображения

Может ли кто-нибудь заставить свой JavaScript работать автономно?

Если кто-нибудь может предоставить рабочий код, это будет здорово.


person Community    schedule 14.04.2009    source источник
comment
Забудьте о JS — вы украдете их блестящее фоновое изображение или нарисуете свое...?   -  person Shog9    schedule 14.04.2009
comment
Я недостаточно хорошо знаю JS, чтобы написать свой собственный, отсюда и причина задать вопрос   -  person    schedule 15.04.2009
comment
Собираетесь ли вы использовать его, чтобы показать, сколько посетителей было на вашей странице? :п   -  person Marius    schedule 13.02.2010
comment
@ Стив, как жаль, что я не прочитал твой комментарий раньше. Связанный обратный отсчет 1 миллиарда старых приложений был просто статической страницей, когда я расширил вопрос, в то время как более поздний обратный отсчет 10 миллиардов песен все еще фактически считался. Даже сегодня обратный отсчет 10 миллиардов песен все еще является динамическим, хотя обратный отсчет закончился, и сценарий обратного отсчета показывает вам только страницу результатов с изображением. Поэтому даже сегодня я думаю, что apple.com/itunes/10-billion-song- обратный отсчет является гораздо лучшим примером (и его чаще искали в течение последних недель), чем статическая старая ссылка.   -  person Arjan    schedule 25.02.2010
comment
См. также cnanney.com/journal/code/apple-style-counter. (к которому я никакого отношения не имею).   -  person Arjan    schedule 14.05.2010


Ответы (5)


Они используют комбинацию CSS и JavaScript. Анимация переворота основана на технологии, подобной CSS Sprite.

Во-первых, у них есть очень высокое изображение под названием filmstrip.png, которое содержит каждое «состояние» флипа для каждого числа (от 0 до 9; взгляните на уменьшенная деталь, и вы поймете, что я имею в виду).

Затем в HTML каждая цифра состоит из трех вложенных элементов:

  • Первый — это элемент-контейнер, в котором width и height заданы размеры одного «состояния» флипа, а overflowhidden. Этот элемент расположен относительно.

  • Второй элемент позиционируется абсолютно (а поскольку первый элемент позиционируется относительно, этот второй элемент позиционируется абсолютно относительно первого элемента).

  • У третьего элемента background-image установлено на filmstrip.png, а width и height установлены на размеры этого изображения.

Затем JavaScript, кажется, быстро изменяет свойство top второго элемента, в результате чего разные части filmstrip.png отображаются одна за другой, что приводит к анимации с переворотом.

Стив

person Steve Harrison    schedule 14.04.2009
comment
Нет, но у меня есть веб-инспектор Safari 4 (apple.com/safari/features.html #разработчик)... - person Steve Harrison; 14.04.2009

Вот он, готовый к использованию на вашей собственной веб-странице http://cnanney.com/journal/code/apple-style-counter-revisited/

person Gunstick    schedule 05.01.2011
comment
Эй, у вас есть метод для создания изображений bg, подобных этому? Я могу найти массу халявы с похожим дизайном, но создать эффект перелистывания сложно. - person Jake; 17.04.2012

Я сделал счетчик, который отлично работает с очень минимальным javascript, чтобы дать ему немного мозгов:

  введите здесь описание изображения

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>

Он отлично выглядит и очень хорошо играет вживую, и его можно считать от любого числа до любого числа.

person vsync    schedule 28.07.2014

В поисках того же самого я нашел коммерческий продукт, предлагающий эту функциональность: Переворот обратного отсчета спрайтов.

Примечание. Я не связан с этим продуктом; но это хорошо сделано и может быть полезно кому-то.

person Jarrod    schedule 03.10.2012

Я рекомендую вариант с открытым исходным кодом: FlipclockJS, который, вероятно, был создан сразу после этого события :)

Github: objectivehtml/FlipClock, доступно через NPM и Bower (не поддерживается)

person Anuga    schedule 18.10.2017