倒计时翻转动画异常:每3-4秒重复错乱问题求助
倒计时翻转动画重复错乱问题解决
问题根源
- 定时器每250ms就调用一次
flipAll,即使倒计时数值未变化也会触发检查,且未判断卡片是否处于动画状态,导致动画叠加错乱。 - CSS中存在语法错误:
.card \>div的反斜杠多余,导致卡片子元素的圆角样式不生效。 - 未利用
previousTimeBetweenDates判断倒计时数值是否变化,造成不必要的函数调用。
修复后的代码
JavaScript
let countDownDate = new Date().setHours(new Date().getHours() + 24); let previousTimeBetweenDates; setInterval(() => { let now = new Date(); let distance = Math.ceil((countDownDate - now) / 1000); // 仅当数值变化时才执行翻转动画 if (distance !== previousTimeBetweenDates) { flipAll(distance); previousTimeBetweenDates = distance; } }, 250); function flip(card, nextNum) { let topHalf = card.querySelector('.top'); let cardnum = parseInt(topHalf.textContent); // 如果数值未变化或卡片正在动画,直接返回 if (nextNum === cardnum || card.classList.contains('animating')) return; // 添加动画状态标记 card.classList.add('animating'); 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(); card.classList.remove('animating'); }); 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); }
CSS
*, *::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; }
HTML
<!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.0"> <title>Countdown Timer</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>
修复要点
- 新增卡片动画状态标记
animating类,确保同一卡片在动画未完成时不会被重复触发。 - 仅当倒计时数值
distance发生变化时才调用flipAll,避免无效调用。 - 修复CSS中的语法错误,保证卡片子元素的圆角样式正常生效。
- 动画结束后及时移除临时元素并清除状态标记,避免DOM堆积。
内容的提问来源于stack exchange,提问作者amr bassem
相关产品推荐
相关产品推荐

