使用 HTML、CSS 和 JavaScript 从零开始构建一个番茄钟应用

引言

番茄工作法(Pomodoro Technique)是一种流行的时间管理方法,它使用一个计时器将工作分解为多个25分钟的专注时段,中间穿插短暂的休息。这种方法有助于提高注意力,减少干扰,从而提升工作和学习效率。

在本教程中,我们将引导您一步步使用前端三大基础技术——HTML、CSS 和 JavaScript——来构建一个功能齐全的网页版番茄钟。您将学习到如何搭建项目结构、设计用户界面、以及实现核心的计时与交互逻辑。无论您是前端初学者还是希望巩固基础知识的开发者,本教程都将为您提供一个绝佳的实践项目。

项目概述

完成本教程后,您将得到一个如下图所示的番茄钟应用:

  • 功能完备: 支持“番茄时间”、“短时休息”和“长时休息”三种模式切换。
  • 交互友好: 拥有开始、暂停和重置计时器的基本控制功能。
  • 界面简洁: 采用现代化且直观的设计,清晰地展示剩余时间。

在这里插入图片描述


一、 先决条件

在开始之前,请确保您已准备好以下工具和知识:

  • 代码编辑器: 如 Visual Studio Code、Sublime Text 或任何您喜欢的编辑器。
  • 网页浏览器: 如 Google Chrome、Firefox 等,用于测试您的应用。
  • 基础知识: 对 HTML、CSS 和 JavaScript 有基本的了解。

二、 项目搭建

首先,我们需要为项目创建一个清晰的文件结构。

  1. 在您的电脑上创建一个新的文件夹,命名为 pomodoro-timer
  2. 在该文件夹内,创建以下三个文件:
    • index.html: 用于定义应用的骨架和内容。
    • style.css: 用于设计应用的外观和样式。
    • script.js: 用于实现应用的所有功能和逻辑。

您的项目目录结构应如下所示:

pomodoro-timer/
├── index.html
├── style.css
└── script.js

三、 第一步:构建 HTML 结构

HTML 负责定义网页的结构。打开 index.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>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div class="container">
        <h1>番茄钟</h1>
        <div class="timer">
            <div class="timer-mode">
                <button id="pomodoro" class="active">番茄时间</button>
                <button id="short-break">短时休息</button>
                <button id="long-break">长时休息</button>
            </div>
            <div class="time-display">25:00</div>
            <div class="timer-controls">
                <button id="start">开始</button>
                <button id="stop" class="hidden">暂停</button>
                <button id="reset" class="hidden">重置</button>
            </div>
        </div>
    </div>
    <script src="script.js"></script>
</body>
</html>

代码解析:

  • <div class="container">: 作为整个应用的主容器。
  • <div class="timer-mode">: 包含三个模式切换按钮,默认“番茄时间”为激活状态 (class="active")。
  • <div class="time-display">: 用于显示倒计时时间,初始值为 “25:00”。
  • <div class="timer-controls">: 包含“开始”、“暂停”和“重置”按钮。“暂停”和“重置”按钮初始时是隐藏的 (class="hidden")。
  • <link><script>: 分别用于链接外部的 CSS 样式表和 JavaScript 脚本文件。

四、 第二步:添加 CSS 样式

现在,我们来为应用添加样式,使其看起来更加美观和专业。打开 style.css 文件,并粘贴以下代码。

:root {
    --primary-color: #d95550;
    --secondary-color: #4c9195;
    --tertiary-color: #457d9b;
    --bg-color: #f0f0f0;
    --font-color: #333;
    --white: #fff;
}

body {
    font-family: Arial, sans-serif;
    background-color: var(--bg-color);
    color: var(--font-color);
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    margin: 0;
}

.container {
    background-color: var(--white);
    padding: 2rem;
    border-radius: 15px;
    box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
    text-align: center;
    width: 90%;
    max-width: 400px;
}

h1 {
    font-size: 2rem;
    margin-bottom: 1.5rem;
}

.timer-mode {
    margin-bottom: 1.5rem;
}

.timer-mode button {
    background: none;
    border: none;
    padding: 0.5rem 1rem;
    margin: 0 0.25rem;
    font-size: 1rem;
    cursor: pointer;
    border-radius: 5px;
    transition: all 0.2s ease-in-out;
}

.timer-mode button.active {
    background-color: var(--primary-color);
    color: var(--white);
}

.time-display {
    font-size: 6rem;
    font-weight: bold;
    margin-bottom: 1.5rem;
}

.timer-controls button {
    border: none;
    padding: 0.8rem 2rem;
    font-size: 1.1rem;
    color: var(--white);
    border-radius: 5px;
    cursor: pointer;
    margin: 0 0.5rem;
    transition: background-color 0.2s ease-in-out;
}

#start {
    background-color: var(--primary-color);
}

#stop {
    background-color: var(--secondary-color);
}

#reset {
    background-color: var(--tertiary-color);
}

.timer-controls button.hidden {
    display: none;
}

/* 动态背景颜色变化 */
body.pomodoro-active { background-color: #f8d7da; }
body.short-break-active { background-color: #d1e7dd; }
body.long-break-active { background-color: #cce5ff; }

样式解析:

  • CSS 变量 (:root): 我们在根元素上定义了颜色变量,方便全局统一修改和维护。
  • Flexbox 布局: 使用 display: flex 将整个容器在页面上垂直和水平居中。
  • .active 类: 用于高亮显示当前选中的计时器模式按钮。
  • .hidden 类: 一个工具类,用于通过 display: none; 来隐藏元素。
  • 动态背景: 我们预留了几个 body 的类名(如 pomodoro-active),准备在切换模式时通过 JavaScript 来改变页面背景色,以提供更丰富的视觉反馈。

五、 第三步:实现 JavaScript 逻辑

这是教程的核心部分。我们将编写 JavaScript 代码来驱动番茄钟的所有功能。打开 script.js 文件,我们将分步实现它。

1. 初始化变量和常量

首先,我们需要获取所有需要操作的 HTML 元素,并定义一些核心变量。

// 获取DOM元素
const timeDisplay = document.querySelector('.time-display');
const pomodoroBtn = document.getElementById('pomodoro');
const shortBreakBtn = document.getElementById('short-break');
const longBreakBtn = document.getElementById('long-break');
const startBtn = document.getElementById('start');
const stopBtn = document.getElementById('stop');
const resetBtn = document.getElementById('reset');

// 定义计时器时间(单位:秒)
const POMODORO_TIME = 25 * 60;
const SHORT_BREAK_TIME = 5 * 60;
const LONG_BREAK_TIME = 15 * 60;

let timer; // 用于存放 setInterval 的 ID
let currentTime = POMODORO_TIME; // 当前剩余时间
let currentMode = 'pomodoro'; // 当前模式
2. 核心功能函数

接下来,我们创建更新时间显示、启动计时器、暂停和重置等核心功能的函数。

// 更新时间显示
function updateDisplay() {
    const minutes = Math.floor(currentTime / 60);
    const seconds = currentTime % 60;
    timeDisplay.textContent = `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
}

// 启动计时器
function startTimer() {
    startBtn.classList.add('hidden');
    stopBtn.classList.remove('hidden');
    resetBtn.classList.remove('hidden');

    timer = setInterval(() => {
        currentTime--;
        updateDisplay();
        if (currentTime <= 0) {
            clearInterval(timer);
            alert("时间到!");
            // 可以在此处添加自动切换到下一个模式的逻辑
        }
    }, 1000);
}

// 暂停计时器
function stopTimer() {
    clearInterval(timer);
    startBtn.textContent = "继续";
    startBtn.classList.remove('hidden');
    stopBtn.classList.add('hidden');
}

// 重置计时器
function resetTimer() {
    clearInterval(timer);
    switch (currentMode) {
        case 'pomodoro':
            currentTime = POMODORO_TIME;
            break;
        case 'short-break':
            currentTime = SHORT_BREAK_TIME;
            break;
        case 'long-break':
            currentTime = LONG_BREAK_TIME;
            break;
    }
    updateDisplay();
    startBtn.textContent = "开始";
    startBtn.classList.remove('hidden');
    stopBtn.classList.add('hidden');
    resetBtn.classList.add('hidden');
}

逻辑解析:

  • updateDisplay(): 将总秒数格式化为 MM:SS 的形式并显示在页面上。padStart(2, '0') 确保始终显示两位数。
  • startTimer(): 使用 setInterval 每秒钟将 currentTime 减一并更新显示。同时,它会切换“开始”和“暂停”按钮的可见性。
  • stopTimer(): 使用 clearInterval 来清除 setInterval,从而暂停计时。它还将“开始”按钮的文本改为“继续”,以便用户理解。
  • resetTimer(): 清除计时器,并根据当前模式将时间重置为初始值,同时恢复控制按钮的初始状态。
3. 模式切换与事件监听

最后,我们需要为所有的按钮添加事件监听器,让用户可以与应用进行交互。

// 切换模式函数
function switchMode(mode) {
    currentMode = mode;
    // 移除所有按钮的 active 类
    pomodoroBtn.classList.remove('active');
    shortBreakBtn.classList.remove('active');
    longBreakBtn.classList.remove('active');
    
    // 移除 body 的背景类
    document.body.classList.remove('pomodoro-active', 'short-break-active', 'long-break-active');

    let activeBtn;
    if (mode === 'pomodoro') {
        currentTime = POMODORO_TIME;
        activeBtn = pomodoroBtn;
        document.body.classList.add('pomodoro-active');
    } else if (mode === 'short-break') {
        currentTime = SHORT_BREAK_TIME;
        activeBtn = shortBreakBtn;
        document.body.classList.add('short-break-active');
    } else {
        currentTime = LONG_BREAK_TIME;
        activeBtn = longBreakBtn;
        document.body.classList.add('long-break-active');
    }
    
    activeBtn.classList.add('active');
    resetTimer(); // 切换模式后总是重置计时器
}


// 添加事件监听器
startBtn.addEventListener('click', startTimer);
stopBtn.addEventListener('click', stopTimer);
resetBtn.addEventListener('click', resetTimer);

pomodoroBtn.addEventListener('click', () => switchMode('pomodoro'));
shortBreakBtn.addEventListener('click', () => switchMode('short-break'));
longBreakBtn.addEventListener('click', () => switchMode('long-break'));


// 页面加载时初始化显示
updateDisplay();

逻辑解析:

  • switchMode(mode): 这是模式切换的核心。它会更新 currentMode 变量,根据新模式设置 currentTime,切换按钮的 .active 状态,并调用 resetTimer() 来应用新的时间。同时,它还会更改 <body>class 来触发我们之前在 CSS 中定义的背景颜色变化。
  • 事件监听: 为每个按钮绑定 click 事件,并链接到相应的处理函数。
  • 初始调用: 在脚本末尾调用 updateDisplay(),确保页面加载完成时能正确显示初始时间 “25:00”。

六、 运行您的番茄钟

恭喜您!现在所有的代码都已经完成。要运行您的番茄钟应用,只需:

  1. 导航到您的 pomodoro-timer 文件夹。
  2. 在您的网页浏览器中直接打开 index.html 文件(可以直接双击文件,或在浏览器地址栏输入文件路径)。

您应该能看到一个功能完整的番茄钟应用在浏览器中运行起来了。
在这里插入图片描述
在这里插入图片描述

七、 如何使用

  1. 选择模式: 点击顶部的“番茄时间”、“短时休息”或“长时休息”来选择您需要的计时模式。
  2. 开始计时: 点击“开始”按钮启动倒计时。
  3. 暂停/继续: 计时开始后,“开始”按钮会变为“暂停”。点击“暂停”可以随时中断计时,再次点击“继续”(原“开始”按钮)可恢复计时。
  4. 重置: 点击“重置”按钮,可以将当前模式的计时器恢复到初始时间。

八、 总结与展望

通过本教程,您不仅构建了一个实用的工具,还实践了前端开发中的几个核心概念:

  • DOM 操作: 使用 JavaScript 获取和修改 HTML 元素。
  • 事件处理: 响应用户的点击等交互行为。
  • 定时器 (setInterval): 实现动态、基于时间的功能。
  • 模块化文件: 将 HTML、CSS 和 JavaScript 分离到不同文件中,使项目结构更清晰、易于维护。

进阶学习与探索

这个项目是一个很好的起点。您可以尝试为其添加更多功能,以深化您的学习:

  • 声音提醒: 在计时结束时播放提示音。
  • 自动循环: 完成一个番茄时间后,自动开始一个短时休息。
  • 任务列表: 在旁边添加一个简单的待办事项列表,让用户可以记录当前专注的任务。
  • 数据持久化: 使用 localStorage 保存用户的设置(如自定义时间)或番茄钟完成的次数。
  • 浏览器通知: 当计时结束且浏览器窗口不处于激活状态时,发送桌面通知。

希望本教程对您有所帮助。祝您编程愉快!

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐