You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为动画编写可用计时器?实现指定时长动画与本地存储暂停功能

动画时长控制与状态存储解决方案

需求说明

  • 通过输入框设置动画运行时长(单位:秒),点击启动按钮后,动画按设定时长运行,结束后自动停止
  • 点击Stop按钮可随时暂停动画,并将当前动画状态(位置、移动方向、剩余时长)存入localStorage

原代码问题点

  1. 动画定时器与倒计时定时器相互独立,无法在时长结束时同步停止动画
  2. Stop按钮仅停止了倒计时,未处理动画的暂停
  3. 缺少localStorage状态存储与恢复逻辑
  4. 动画函数存在变量作用域冲突(内部重定义同名函数)

修改后的完整代码

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 17:45:28