Javascirpt前端教学:利用requestAnimationFrame做计时器-由Deepseek产生

这是为您精简的"最朴素"秒计时器 HTML 代码,去除了所有装饰性样式,只保留核心计时功能与极简界面。

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>朴素秒计时器</title>
    <style>
        /* -------------------- 最大朴素化 -------------------- */
        /* 无圆角、无阴影、无渐变、无动画、无花哨颜色,仅有最基础的结构 */

        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            background: #ffffff;
            color: #000000;
            font-family: 'Courier New', Courier, monospace; /* 等宽字体,朴素直观 */
            min-height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
            text-align: center;
            padding: 1.5rem;
        }

        .container {
            border: 1px solid #888;
            padding: 2.5rem 3rem;
            background: transparent;
        }

        /* 计时器数字:大、粗、纯黑 */
        .timer-display {
            font-size: 5rem;
            font-weight: 700;
            letter-spacing: 0.05em;
            line-height: 1.2;
            color: #000;
        }

        .timer-display .decimal {
            font-size: 3.2rem;
            font-weight: 400;
        }

        /* 状态文字:灰色,不加任何修饰 */
        .status-area {
            margin-top: 1.2rem;
            font-size: 1.1rem;
            color: #444;
            border-top: 1px solid #aaa;
            padding-top: 1rem;
            display: flex;
            justify-content: center;
            gap: 1.2rem;
            align-items: baseline;
        }

        .status-dot {
            display: inline-block;
            width: 12px;
            height: 12px;
            border: 1px solid #222;
            background: #222; /* 运行中为黑色 */
        }

        .status-dot.paused {
            background: #fff; /* 暂停为白色(空心) */
            border-color: #888;
        }

        /* 按钮:极简边框,无背景色,悬停仅加粗边框 */
        .controls {
            margin-top: 1.8rem;
            display: flex;
            gap: 0.8rem;
            justify-content: center;
        }

        .controls button {
            font-family: 'Courier New', Courier, monospace;
            font-size: 1.1rem;
            font-weight: 400;
            padding: 0.4rem 1.6rem;
            background: #fff;
            color: #000;
            border: 1px solid #222;
            cursor: pointer;
            transition: none; /* 无过渡动画 */
            letter-spacing: 0.04em;
        }

        /* 朴素交互:仅改变边框粗细与颜色 */
        .controls button:hover {
            border-color: #000;
            border-width: 2px;
            background: #f8f8f8;
        }

        .controls button:active {
            background: #ddd;
            border-color: #000;
        }

        /* 重置按钮保持完全一致,不加特殊颜色 */
        .controls button.reset-btn {
            border-color: #666;
        }

        .controls button.reset-btn:hover {
            border-color: #000;
            background: #f8f8f8;
        }

        /* 极简响应式:只调整字号 */
        @media (max-width: 500px) {
            .container {
                padding: 1.5rem 1.2rem;
            }
            .timer-display {
                font-size: 3.6rem;
            }
            .timer-display .decimal {
                font-size: 2.2rem;
            }
            .controls button {
                font-size: 1rem;
                padding: 0.3rem 1rem;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <!-- 计时器显示:秒.百分秒 -->
        <div class="timer-display">
            <span id="secondsDisplay">0</span>
            <span class="decimal">.<span id="centisecondsDisplay">00</span></span>
        </div>

        <!-- 状态区域:黑色方块=运行,白色方块=暂停 -->
        <div class="status-area">
            <span class="status-dot" id="statusDot"></span>
            <span id="statusText">运行中</span>
        </div>

        <!-- 控制按钮 -->
        <div class="controls">
            <button id="pauseBtn">暂停</button>
            <button id="resetBtn" class="reset-btn">重置</button>
        </div>
    </div>

    <script>
        (function() {
            'use strict';

            // ---------- DOM 引用 ----------
            const secondsEl = document.getElementById('secondsDisplay');
            const centisecondsEl = document.getElementById('centisecondsDisplay');
            const statusDot = document.getElementById('statusDot');
            const statusText = document.getElementById('statusText');
            const pauseBtn = document.getElementById('pauseBtn');
            const resetBtn = document.getElementById('resetBtn');

            // ---------- 计时器状态 ----------
            let startTime = 0;               // 当前计时周期起始时间 (ms)
            let accumulatedTime = 0;         // 已累计时间 (ms)
            let paused = false;              // 是否暂停
            let animationId = null;

            // ---------- 更新显示 (百分秒精度) ----------
            function updateDisplay(totalMs) {
                const totalSeconds = totalMs / 1000;
                const seconds = Math.floor(totalSeconds);
                const centiseconds = Math.floor((totalSeconds - seconds) * 100);

                secondsEl.textContent = seconds;
                centisecondsEl.textContent = String(centiseconds).padStart(2, '0');
            }

            // ---------- 动画循环 (核心) ----------
            function tick(timestamp) {
                if (!paused) {
                    const elapsed = accumulatedTime + (timestamp - startTime);
                    updateDisplay(elapsed);
                }
                animationId = requestAnimationFrame(tick);
            }

            // ---------- 启动 / 恢复 ----------
            function startTimer() {
                if (animationId) {
                    cancelAnimationFrame(animationId);
                    animationId = null;
                }
                startTime = performance.now();

                if (paused) {
                    paused = false;
                    updateStatusUI(false);
                }
                animationId = requestAnimationFrame(tick);
            }

            // ---------- 暂停 ----------
            function pauseTimer() {
                if (paused) return;

                if (animationId) {
                    cancelAnimationFrame(animationId);
                    animationId = null;
                }

                const now = performance.now();
                accumulatedTime += (now - startTime);

                paused = true;
                updateStatusUI(true);
                pauseBtn.textContent = '继续';
            }

            // ---------- 恢复 ----------
            function resumeTimer() {
                if (!paused) return;

                startTime = performance.now();
                paused = false;
                updateStatusUI(false);
                pauseBtn.textContent = '暂停';

                if (animationId) {
                    cancelAnimationFrame(animationId);
                    animationId = null;
                }
                animationId = requestAnimationFrame(tick);
            }

            // ---------- 重置 ----------
            function resetTimer() {
                if (animationId) {
                    cancelAnimationFrame(animationId);
                    animationId = null;
                }

                accumulatedTime = 0;
                paused = false;
                startTime = performance.now();

                updateDisplay(0);
                updateStatusUI(false);
                pauseBtn.textContent = '暂停';

                animationId = requestAnimationFrame(tick);
            }

            // ---------- 状态 UI ----------
            function updateStatusUI(isPaused) {
                if (isPaused) {
                    statusDot.className = 'status-dot paused';
                    statusText.textContent = '已暂停';
                } else {
                    statusDot.className = 'status-dot';
                    statusText.textContent = '运行中';
                }
            }

            // ---------- 切换暂停/继续 ----------
            function togglePause() {
                if (paused) {
                    resumeTimer();
                } else {
                    pauseTimer();
                }
            }

            // ---------- 初始化 ----------
            function init() {
                accumulatedTime = 0;
                paused = false;
                startTime = performance.now();
                updateDisplay(0);
                updateStatusUI(false);
                pauseBtn.textContent = '暂停';

                if (animationId) {
                    cancelAnimationFrame(animationId);
                    animationId = null;
                }
                animationId = requestAnimationFrame(tick);

                pauseBtn.addEventListener('click', togglePause);
                resetBtn.addEventListener('click', resetTimer);
            }

            // 页面卸载时清理
            window.addEventListener('beforeunload', function() {
                if (animationId) {
                    cancelAnimationFrame(animationId);
                    animationId = null;
                }
            });

            init();

        })();
    </script>
</body>
</html>

极简计时与操作

这个计时器以最"朴素"的方式呈现,专注于核心功能,没有任何多余视觉干扰。

  • 计时与显示:界面中央以等宽字体清晰显示"秒.百分秒"格式的时间,精度达到百分之一秒。
  • 核心控制:通过"暂停/继续"和"重置"两个按钮管理计时流程。点击"暂停"可冻结当前计时,再次点击则从同一时刻恢复;"重置"按钮会将计时归零并自动开始。
  • 状态反馈:状态区域使用一个简单的方块指示器(黑色代表运行中,白色代表暂停)和文字说明,让您随时了解计时器当前的工作状态。

优化建议 :您可以直接修改 CSS 中 。timer-displayfont-size 数值来调整计时数字的大小,或调整 bodybackgroundcolor 来更换页面底色与文字颜色。