Анимация обратного отсчета на чистом CSS

Я пытаюсь сделать чистую анимацию обратного отсчета HTML/CSS, но я изо всех сил пытаюсь заставить ее работать гладко. Пока я говорю только о минутах и ​​секундах. Обратите внимание, что я использую свойство animation-delay для сброса обратного отсчета до определенного начального времени.

На данный момент все работает нормально, за исключением цифры, соответствующей х10 минутам, которая не меняется синхронно с остальными цифрами. Далее я вставлю свой код и две кодовые ручки, первую нормальную версию с правильными таймингами для нормального поведения и еще одну в 10 раз быстрее, чтобы вы могли быстро оценить проблему.

@keyframes tick6 {
        0%      { margin-top: 0; }
        16%     { margin-top: -2rem;  }
        33%     { margin-top: -4rem;  }
        50%     { margin-top: -6rem;  }
        66%     { margin-top: -8rem;  }
        83%     { margin-top: -10rem;  }
        100%    { margin-top: -12rem;  }
    }

    @keyframes tick10 {
        0%      { margin-top: 0; }
        10%     { margin-top: -2rem;  }
        20%     { margin-top: -4rem;  }
        30%     { margin-top: -6rem;  }
        40%     { margin-top: -8rem;  }
        50%     { margin-top: -10rem;  }
        60%     { margin-top: -12rem;  }
        70%     { margin-top: -14rem;  }
        80%     { margin-top: -16rem;  }
        90%     { margin-top: -18rem;  }
        100%    { margin-top: -20rem;  }
    }
    
body {
  background-color: black;
}

.container {
  background-color: white;
}

.digit {
  display: inline-block;
  height: 2rem;
  overflow: hidden;
  width: 1ch;
}

.digit span {
  display: block;
  height: 2rem;
  width: 100%;
}

.minutes-digit-one {
  animation: tick6 3600s step-end;
  animation-iteration-count: infinite;
  animation-delay: -540s;
}

.minutes-digit-two {
  animation: tick10 600s step-end;
  animation-iteration-count: infinite;
  animation-delay: -540s;
}

.seconds-digit-one {
  animation: tick6 60s step-end;
  animation-iteration-count: infinite;
  animation-delay: -540s;
}

.seconds-digit-two {
  animation: tick10 10s;
  animation-iteration-count: infinite;
  animation-delay: -540s;
}
<div class="container">
  <div class="digit">
    <span class="minutes-digit-one">5</span>
    <span>4</span>
    <span>3</span>
    <span>2</span>
    <span>1</span>
    <span>0</span>
    <span>5</span>
  </div>
  <div class="digit">
    <span class="minutes-digit-two">9</span>
    <span>8</span>
    <span>7</span>
    <span>6</span>
    <span>5</span>
    <span>4</span>
    <span>3</span>
    <span>2</span>
    <span>1</span>
    <span>0</span>
    <span>9</span>
  </div>
  <div class="digit">
    <span>:</span>
  </div>
  <div class="digit">
    <span class="seconds-digit-one">5</span>
    <span>4</span>
    <span>3</span>
    <span>2</span>
    <span>1</span>
    <span>0</span>
    <span>5</span>
  </div>
  <div class="digit">
    <span class="seconds-digit-two">9</span>
    <span>8</span>
    <span>7</span>
    <span>6</span>
    <span>5</span>
    <span>4</span>
    <span>3</span>
    <span>2</span>
    <span>1</span>
    <span>0</span>
    <span>9</span>
  </div>
</div>


person Esteban Cazorla    schedule 30.07.2018    source источник


Ответы (1)


Это связано с процентными значениями ключевых кадров. Вы используете 16%, в то время как должно быть 16.6667% (100/6), чтобы быть более точным и точным, то же самое с другими значениями.

При использовании 360s или 3600s в качестве длительности у вас будет четкая разница между 16% и 16.6667%, поэтому состояние изменится раньше, и у вас возникнет проблема с синхронизацией. Вы можете не заметить этого при использовании 6s в качестве длительности с секундами.

@keyframes tick6 {  
    0%          { margin-top: 0; }      /* 0*(100/6) */
    16.6667%    { margin-top: -2rem;  } /* 1*(100/6) */
    33.3333%    { margin-top: -4rem;  } /* 2*(100/6) */
    50%         { margin-top: -6rem;  } /* 3*(100/6) */
    66.6667%    { margin-top: -8rem;  } /* 4*(100/6) */
    83.3333%    { margin-top: -10rem; } /* 5*(100/6) */
    100%        { margin-top: -12rem; } /* 6*(100/6) */
}

@keyframes tick10 {
    0%      { margin-top: 0; }
    10%     { margin-top: -2rem;  }
    20%     { margin-top: -4rem;  }
    30%     { margin-top: -6rem;  }
    40%     { margin-top: -8rem;  }
    50%     { margin-top: -10rem;  }
    60%     { margin-top: -12rem;  }
    70%     { margin-top: -14rem;  }
    80%     { margin-top: -16rem;  }
    90%     { margin-top: -18rem;  }
    100%    { margin-top: -20rem;  }
}

body {
  background-color: black;
}

.container {
  background-color: white;
}

.digit {
  display: inline-block;
  height: 2rem;
  overflow: hidden;
  width: 1ch;
}

.digit span {
  display: block;
  height: 2rem;
  width: 100%;
}

.minutes-digit-one {
  animation: tick6 360s infinite step-end;
  /*animation-delay: -54s;*/
}

.minutes-digit-two {
  animation: tick10 60s infinite step-end;
  /*animation-delay: -54s;*/
}

.seconds-digit-one {
  animation: tick6 6s infinite step-end;
  /*animation-delay: -54s;*/
}

.seconds-digit-two {
  animation: tick10 1s infinite step-end;
}
<div class="container">
  <div class="digit">
    <span class="minutes-digit-one">5</span>
    <span>4</span>
    <span>3</span>
    <span>2</span>
    <span>1</span>
    <span>0</span>
    <span>5</span>
  </div>
  <div class="digit">
    <span class="minutes-digit-two">9</span>
    <span>8</span>
    <span>7</span>
    <span>6</span>
    <span>5</span>
    <span>4</span>
    <span>3</span>
    <span>2</span>
    <span>1</span>
    <span>0</span>
    <span>9</span>
  </div>
  <div class="digit">
    <span>:</span>
  </div>
  <div class="digit">
    <span class="seconds-digit-one">5</span>
    <span>4</span>
    <span>3</span>
    <span>2</span>
    <span>1</span>
    <span>0</span>
    <span>5</span>
  </div>
  <div class="digit">
    <span class="seconds-digit-two">9</span>
    <span>8</span>
    <span>7</span>
    <span>6</span>
    <span>5</span>
    <span>4</span>
    <span>3</span>
    <span>2</span>
    <span>1</span>
    <span>0</span>
    <span>9</span>
  </div>
</div>

person Temani Afif    schedule 30.07.2018
comment
И, чтобы быть совершенно ясным, 16.6667 технически отключен. Технически это 16,6666 (повторяется бесконечно), но я не уверен, что разница вызовет долгосрочные расхождения - person random_user_name; 30.07.2018
comment
@cale_b математически это 16,6666 (повторяя), а точнее 100/6, как я описал в ответе, но в реальном мире 16,666...% - это то же самое, что и 16,6667%, все приблизительно;) и наше восприятие не будет учитываться эту маленькую разницу, если только мы не имеем дело с очень частным случаем, требующим большего количества вычислений. - person Temani Afif; 30.07.2018
comment
@cale_b также в этом случае у нас не будет долговременных расхождений, поскольку продолжительность фиксируется как 360 секунд, поэтому цикл будет повторяться точно каждые 360 секунд. Если это хорошо для первого, то это будет хорошо для второго и так далее... у нас могут возникнуть проблемы, если продолжительность не точна, и это может создать несоответствия - person Temani Afif; 30.07.2018