如何为动画编写可用计时器?实现指定时长动画与本地存储暂停功能
动画时长控制与状态存储解决方案
需求说明
- 通过输入框设置动画运行时长(单位:秒),点击启动按钮后,动画按设定时长运行,结束后自动停止
- 点击Stop按钮可随时暂停动画,并将当前动画状态(位置、移动方向、剩余时长)存入
localStorage
原代码问题点
- 动画定时器与倒计时定时器相互独立,无法在时长结束时同步停止动画
- Stop按钮仅停止了倒计时,未处理动画的暂停
- 缺少
localStorage状态存储与恢复逻辑 - 动画函数存在变量作用域冲突(内部重定义同名函数)
修改后的完整代码
HTML
<body> <div class="wrapper"> <div class="container"> <div class="animation"></div> </div> <input id="timer" type="number" value="0" placeholder="输入时长(秒)"> <p id="timerr">00</p> </div> <div class="ball"> <button id="up" class="btn fa-solid fa-caret-up">启动</button> </div> <button class="btn stop"><i class="fa-solid fa-hand"></i> Stop</button> <script src="script.js"></script> </body> </html>
CSS
@import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.2/css/all.min.css'); * { margin: 0; padding: 0; box-sizing: border-box; } .wrapper { width: 400px; margin: 0 auto; text-align: center; } .container { width: 400px; height: 400px; position: relative; background-color: #b8f9f4; } .animation { width: 50px; height: 50px; border-radius: 50%; background-color: crimson; position: absolute; margin: auto; top: 0; bottom: 0; left: 0; right: 0; } button { display: flex; width: 90px; height: 60px; border: 0; box-sizing: content-box; margin: 5px 0; } .ball { display: flex; justify-content: center; align-items: center; } .fa-solid { font-size: 60px; } .btn { text-align: center; padding: 5px; cursor: pointer; justify-content: center; align-items: center; } .stop { font-size: 18px; margin: auto; top: 0; left: 0; right: 0; bottom: 0; } .fa-hand { font-size: 24px; }
JavaScript
// 获取DOM元素 const anm = document.querySelector('.animation'); const upBtn = document.getElementById('up'); const stopBtn = document.querySelector('.stop'); const timerInput = document.getElementById('timer'); const timerDisplay = document.getElementById('timerr'); // 全局状态变量 let animationInterval = null; let countdownInterval = null; let position = 0; let setPosUp = 350; let add = 1; let countSeconds = 0; // 检查localStorage,恢复之前的状态 function restoreState() { const savedState = localStorage.getItem('animationState'); if (savedState) { const { position: savedPos, add: savedDir, countSeconds: savedTime } = JSON.parse(savedState); position = savedPos; add = savedDir; countSeconds = savedTime; anm.style.bottom = `${position}px`; timerDisplay.textContent = countSeconds; timerInput.value = countSeconds; } } // 动画核心函数 function animateBall() { if (position === setPosUp) { setPosUp = position === 0 ? 350 : 0; add *= -1; } else { position += add; anm.style.bottom = `${position}px`; } } // 启动动画与倒计时 function startAnimation() { // 清除已有定时器,避免重复启动 clearInterval(animationInterval); clearInterval(countdownInterval); // 获取输入的时长,默认0 countSeconds = parseInt(timerInput.value) || 0; timerDisplay.textContent = countSeconds; // 启动动画 animationInterval = setInterval(animateBall, 1); // 启动倒计时 countdownInterval = setInterval(() => { countSeconds--; timerDisplay.textContent = countSeconds; if (countSeconds <= 0) { stopAnimation(); timerDisplay.textContent = '0'; } }, 1000); } // 暂停动画并存储状态 function stopAnimation() { clearInterval(animationInterval); clearInterval(countdownInterval); animationInterval = null; countdownInterval = null; // 存储当前状态到localStorage const state = { position, add, countSeconds }; localStorage.setItem('animationState', JSON.stringify(state)); } // 页面加载时恢复状态 window.addEventListener('load', restoreState); // 绑定按钮事件 upBtn.addEventListener('click', startAnimation); stopBtn.addEventListener('click', stopAnimation);
关键改进点
- 统一管理动画和倒计时定时器,确保启动/暂停同步执行
- 新增状态恢复逻辑,页面加载时自动读取
localStorage保存的进度 - 暂停时将动画位置、移动方向、剩余时长序列化为JSON存入本地存储
- 修复原动画函数的作用域冲突问题,拆分独立的动画核心逻辑
- 启动时自动清除已有定时器,避免多次点击导致的动画加速
内容的提问来源于stack exchange,提问作者Alexander
相关产品推荐
相关产品推荐

