html 为什么翻转动画在4到5秒后不能正常发生

7kqas0il  于 2023-03-27  发布在  其他
关注(0)|答案(1)|浏览(118)

我的倒数计时器动画被加倍(损坏)每隔几秒(约3至4秒,也许更少),我不知道为什么。

let countDownDate = new Date().setHours(new Date().getHours() + 24)
let previousTimeBetweenDates;
setInterval(() => {
  let now = new Date()
  let distance = Math.ceil((countDownDate - now) / 1000)
  flipAll(distance)
  previousTimeBetweenDates = distance
}, 250);

function flip(card, nextNum) {
  let topHalf = card.querySelector('.top');
  let cardnum = parseInt(topHalf.textContent)
  if (nextNum === cardnum) return
  // topHalf.textContent = cardnum

  let flipTop = document.createElement('div');
  flipTop.classList.add('flip-top');

  let flipBottom = document.createElement('div');
  flipBottom.classList.add('flip-bottom');

  let bottomHalf = card.querySelector('.bottom');

  bottomHalf.textContent = cardnum
  flipBottom.textContent = cardnum
  flipTop.textContent = nextNum
  topHalf.textContent = cardnum
  flipTop.addEventListener('animationstart', e => {
    topHalf.textContent = nextNum
  })
  flipTop.addEventListener('animationend', e => {
    flipTop.remove()
  })
  flipBottom.addEventListener('animationend', e => {
    bottomHalf.textContent = nextNum
    flipBottom.remove()
  })
  card.append(flipTop, flipBottom);

}

function flipAll(date) {
  let seconds = date % 60
  let minutes = Math.floor(date / 60) % 60
  let hours = Math.floor(date / 3600)
  flip(document.querySelector('.hours-tens'), Math.floor(hours / 10))
  flip(document.querySelector('.hours-units'), hours % 10)
  flip(document.querySelector('.minutes-tens'), Math.floor(minutes / 10))
  flip(document.querySelector('.minutes-units'), minutes % 10)
  flip(document.querySelector('.seconds-tens'), Math.floor(seconds / 10))
  flip(document.querySelector('.seconds-units'), seconds % 10)
}
*,
* ::before,
* ::after {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
  font-family: 'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif;
}

body {
  background-color: #f2f1ed;
  display: grid;
  place-items: center;
  height: 100vh;
}

.card {
  position: relative;
  width: 0.5em;
  display: flex;
  flex-direction: column;
  font-size: 8rem;
  color: #de4848;
  font-weight: 600;
  box-shadow: 0 0 10px 1px rgba(0, 0, 0, 0.2);
  border-collapse: separate;
  border-radius: .1em;
}

.card \>div {
  border-radius: .1em;
}

.part,
.card .flip-top,
.card .flip-bottom {
  height: .75em;
  padding: .25em;
  line-height: 1;
  display: flex;
  justify-content: center;
}

.top,
.card .flip-bottom {
  background-color: #f7f7f7;
  border-bottom: 1px solid rgb(201, 201, 201);
}

.card .flip-bottom {
  position: absolute;
  width: 100%;
  height: 50%;
  background: #f7f7f7;
  overflow: hidden;
  text-align: center;
  padding-top: .25em;
  line-height: 1;
  animation: flip-down 250ms ease-in;
  transform-origin: bottom;
}

.card .flip-top {
  position: absolute;
  width: 100%;
  bottom: 0;
  animation: flip-up 250ms ease-out 250ms;
  transform-origin: top;
  transform: rotateX(90deg);
}

@keyframes flip-down {
  100% {
    transform: rotateX(90deg);
  }
}

@keyframes flip-up {
  100% {
    transform: rotateX(0deg);
  }
}

.bottom,
.card .flip-top {
  display: flex;
  align-items: flex-end;
  background-color: white;
}

.big-container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  place-items: center;
  gap: 3em;
}

.container {
  display: flex;
  flex-direction: column;
  gap: 1em;
}

.title {
  text-align: center;
  font-weight: 400;
}

.inner-container {
  display: flex;
  gap: 1em;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.">
  <title>Document</title>
  <link rel="stylesheet" href="style.css">
</head>

<body>
  <div class="big-container">
    <div class="hours-container container">
      <div class="inner-container">
        <div class="hours card flip hours-tens">
          <div class="top part">2</div>
          <div class="bottom part">2</div>
        </div>
        <div class="hours card flip hours-units">
          <div class="top part">4</div>
          <div class="bottom part">4</div>
        </div>
      </div>
      <h1 class="hours-title title">Hours</h1>
    </div>
    <div class="minutes-container container">
      <div class="inner-container">
        <div class="minutes card flip minutes-tens">
          <div class="top part">0</div>
          <div class="bottom part">0</div>
        </div>
        <div class="minutes card flip minutes-units">
          <div class="top part">0</div>
          <div class="bottom part">0</div>
        </div>
      </div>
      <h1 class="minutes-title title">Minutes</h1>
    </div>
    <div class="seconds-container container">
      <div class="inner-container">
        <div class="seconds card flip seconds-tens">
          <div class="top part">0</div>
          <div class="bottom part">0</div>
        </div>
        <div class="seconds card flip seconds-units">
          <div class="top part">0</div>
          <div class="bottom part">0</div>
        </div>
      </div>
      <h1 class="seconds-title title">Seconds</h1>
    </div>
  </div>
  <script src="script.js"></script>
</body>

</html>

我试着改变动画时间,稍微改变了一下代码,问了一些像ChatGPT和Bing Chat这样的AI机器人,但都没用。

ulydmbyx

ulydmbyx1#

问题是setInterval不能保证每次250ms都被调用,即使这是您设置的时间间隔。
setInterval只承诺在 * 250ms之后调用你的函数。而不是在 * 精确地 * 250ms这意味着你的间隔将开始漂移,因为它可以被延迟多达一个额外的200ms
该解决方案需要使用requestAnimationFrame和实时循环来跟踪增量时间。

// The animate function
let animate = () => {
  console.log("* animating");
}

// The required delay in milliseconds
let delay = 250;

// Current time
let time = Date.now();

// Update function called every frame
// which should be 60 times per second
let update = () => {

  // If delta time is greater than or
  // equal to the delay, do the animation
  // and reset the timer
  if ((Date.now() - time) >= delay) {
    animate();
    time = Date.now();
  }

  // Request the next animation frame
  // and have it call this function which
  // continues the real-time loop
  requestAnimationFrame(update);
}

// Start the real-time loop
update();

相关问题