极简番茄钟 + 任务看板:纯前端 Pomodoro 工具深度解析

0 阅读7分钟

极简番茄钟 + 任务看板:纯前端 Pomodoro 工具深度解析

关键词:Pomodoro、番茄钟、任务看板、纯前端、localStorage、CSS动画、requestAnimationFrame、暗色模式、响应式设计


一、什么是 Pomo-Board?

在快节奏的开发工作中,时间管理和任务追踪是提升效率的关键。番茄工作法(Pomodoro Technique)通过将工作时间划分为 25 分钟专注段和 5 分钟休息段,帮助开发者保持高效专注。

Pomo-Board 是 Toolion 平台(工具狮轻量应用中心)中的一个纯前端应用,它将番茄钟计时器任务看板合二为一,提供了一站式的专注力管理方案。所有功能完全在浏览器端运行,无需后端服务,零配置开箱即用。

项目地址:极简番茄钟 + 任务看板

在这里插入图片描述


二、核心功能概览

功能说明
番茄钟计时器圆形进度环动画,专注/休息模式自动切换
任务管理添加、完成、删除任务,任务列表实时更新
数据统计每日番茄钟计数,持久化存储不丢失
多种时长预设25/5、30/5、45/10 三种经典配置一键切换
暗色/亮色模式一键切换主题,偏好自动保存
音频提醒计时结束时播放提示音,视觉闪烁双重通知
键盘快捷键Enter 添加任务,空格键开始/暂停计时
每日自动重置每天零点自动清空任务和计数

三、技术架构

3.1 整体架构

┌─────────────────────────────────────────────────┐
│                    客户端 (Browser)                    │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────┐ │
│  │  番茄钟计时器  │  │  任务看板    │  │  设置系统  │ │
│  │  requestAnim  │  │  localStorage│  │  主题切换  │ │
│  │  CSS conic   │  │  任务CRUD    │  │  预设配置  │ │
│  │  进度环      │  │  计数统计    │  │  每日重置  │ │
│  └──────────────┘  └──────────────┘  └──────────┘ │
│  ┌──────────────┐  ┌──────────────┐              │
│  │  音频通知    │  │  键盘事件    │              │
│  │  Web Audio   │  │  Enter/Space │              │
│  └──────────────┘  └──────────────┘              │
└──────────────────────┬──────────────────────────┘
                         │ 纯前端,无后端依赖
┌──────────────────────▼──────────────────────────┐
│              Toolion 平台                          │
│  ┌──────────┐  ┌──────────┐  ┌──────────────┐  │
│  │  应用列表  │  │  路由注册  │  │  静态资源服务  │  │
│  └──────────┘  └──────────┘  └──────────────┘  │
└─────────────────────────────────────────────────┘

3.2 技术栈

层级技术选型说明
前端框架原生 HTML/CSS/JS零框架依赖,极致轻量
构建工具npx serve静态文件服务,开发即启
样式方案CSS 自定义属性主题切换、响应式布局
状态管理全局 state 对象集中式状态管理
持久化localStorage浏览器本地存储
动画引擎requestAnimationFrame流畅的计时动画
音频通知Web Audio API浏览器端音效合成
图标SVG + Emoji轻量级图标方案

四、核心实现详解

4.1 番茄钟计时器

番茄钟是应用的核心功能,采用 requestAnimationFrame 实现高精度计时,配合 CSS conic-gradient 实现圆形进度环动画。

计时循环实现

const tick = (timestamp) => {
  if (!state.lastTick) state.lastTick = timestamp;
  
  const elapsed = (timestamp - state.lastTick) / 1000;
  state.lastTick = timestamp;
  
  if (state.timeRemaining > 0) {
    state.timeRemaining -= elapsed;
    if (state.timeRemaining < 0) state.timeRemaining = 0;
    updateTimerDisplay();
    state.rafId = requestAnimationFrame(tick);
  } else {
    endTimer();
  }
};

state.rafId = requestAnimationFrame(tick);

圆形进度环

进度环使用 CSS conic-gradient 实现,通过动态更新 --progress 变量来改变渐变色带的角度:

.timer-ring {
  background: conic-gradient(
    var(--accent) 0deg,
    var(--accent) var(--progress, 0deg),
    var(--border) var(--progress, 0deg),
    var(--border) 360deg
  );
  -webkit-mask: radial-gradient(closest-side, white 85%, transparent 85%);
  mask: radial-gradient(closest-side, white 85%, transparent 85%);
}

这种实现方式避免了 SVG 或 Canvas 的复杂性,仅用 CSS 即可实现流畅的进度动画。

4.2 任务管理

任务模块实现了完整的 CRUD 功能,所有操作即时持久化到 localStorage

任务数据结构

{
  id: Date.now(),        // 唯一标识
  text: "任务内容",       // 任务文本
  completed: false,      // 完成状态
  createdAt: Date.now()  // 创建时间
}

任务添加与完成

function addTask() {
  const text = elements.taskInput.value.trim();
  if (!text) return;
  
  const newTask = {
    id: Date.now(),
    text,
    completed: false,
    createdAt: Date.now()
  };
  
  state.tasks.unshift(newTask);
  input.value = '';
  renderTasks();
  saveToStorage();
}

function toggleTask(index) {
  const task = state.tasks[index];
  task.completed = !task.completed;
  
  if (task.completed) {
    state.pomodoroCount++;
  } else {
    state.pomodoroCount = Math.max(0, state.pomodoroCount - 1);
  }
  
  renderTasks();
  updatePomodoroCount();
  saveToStorage();
}

番茄计数联动:每完成一个任务,番茄计数自动加 1;取消完成时自动减 1,确保数据一致性。

4.3 模式切换与自动流转

番茄钟支持专注模式和休息模式的无缝切换:

function endTimer() {
  if (state.settings.currentMode === 'focus') {
    state.settings.currentMode = 'break';
  } else {
    state.settings.currentMode = 'focus';
  }
  
  updateTimeRemaining();
  elements.timerBtn.textContent = '开始';
  
  playNotificationSound();
  flashTimer();
}

计时结束后自动切换模式,并触发音频通知和视觉闪烁提醒。

4.4 主题系统

通过 CSS 自定义属性和 data-theme 属性实现亮色/暗色模式切换:

[data-theme="light"] {
  --bg: #f5f5f5;
  --surface: #ffffff;
  --text: #1a1a1a;
  --accent: #2563eb;
  --success: #22c55e;
}

[data-theme="dark"] {
  --bg: #1a1a1a;
  --surface: #252525;
  --text: #e0e0e0;
  --accent: #3b82f6;
  --success: #22c55e;
}

主题偏好通过 localStorage 自动保存,下次打开自动恢复。

4.5 音频通知

使用 Web Audio API 在计时结束时生成提示音,无需任何外部音频文件:

function playNotificationSound() {
  const audioContext = new (window.AudioContext || window.webkitAudioContext)();
  const oscillator = audioContext.createOscillator();
  const gainNode = audioContext.createGain();
  
  oscillator.connect(gainNode);
  gainNode.connect(audioContext.destination);
  
  oscillator.frequency.setValueAtTime(800, audioContext.currentTime);
  gainNode.gain.setValueAtTime(0.1, audioContext.currentTime);
  gainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + 0.2);
  
  oscillator.start(audioContext.currentTime);
  oscillator.stop(audioContext.currentTime + 0.2);
}

4.6 键盘快捷键

应用支持全局键盘快捷键,提升操作效率:

function handleKeyDown(e) {
  if (e.key === 'Enter' && document.activeElement === elements.taskInput) {
    addTask();
  }
  
  if (e.key === ' ' && e.target.tagName !== 'INPUT' && e.target.tagName !== 'BUTTON') {
    e.preventDefault();
    startTimer();
  }
}
  • Enter:在输入框中快速添加任务
  • 空格键:全局开始/暂停计时器
  • 点击计时器:点击圆形计时器区域也可开始/暂停

4.7 每日自动重置

通过检测日期变化实现每日零点自动重置:

const today = new Date().toDateString();
const lastReset = localStorage.getItem('pomo_last_reset');
if (lastReset !== today) {
  state.tasks = [];
  state.pomodoroCount = 0;
  localStorage.setItem('pomo_last_reset', today);
}

五、前端页面结构

5.1 整体布局

┌─────────────────────────────────────────────────┐
│  导航栏:返回 │ 🍅 标题 │ 暗色/亮色切换          │
├─────────────────────────────────────────────────┤
│  今日任务    🍅 0                                │
├──────────────────────┬──────────────────────────┤
│                      │                          │
│  任务输入区           │    番茄钟计时器           │
│  ┌──────────┐ +      │    ┌────────────┐       │
│  │ 输入框    │       │    │  圆形进度环  │       │
│  └──────────┘       │    │  25:00      │       │
│                      │    │  专注中      │       │
│  任务列表            │    ├────────────┤       │
│  ┌────────────┐     │    │ 25/5 30/5  │       │
│  │ ☐ 任务1    │     │    │ [开始][重置] │       │
│  │ ☑ 任务2    │     │    └────────────┘       │
│  │ ☐ 任务3    │     │                          │
│  └────────────┘     │                          │
│                      │                          │
├──────────────────────┴──────────────────────────┤
│  底部:粤ICP备... · Toolion · 工具狮 © 2026      │
└─────────────────────────────────────────────────┘

5.2 响应式设计

  • 移动端(< 480px):任务区和计时器垂直堆叠,计时器缩小至 160px
  • 桌面端(≥ 1024px):任务区和计时器左右并排布局,最大宽度 1024px
  • 平板端:自适应中间尺寸

六、项目结构

apps/pomo-board/
├── index.html              # HTML 入口,包含完整样式和结构
├── app.js                  # 核心逻辑:计时器、任务管理、主题切换
├── package.json            # 依赖配置(仅需 npx serve)
├── favicon.svg             # 应用图标(SVG 格式)
└── assets/
    └── theme.js            # 主题管理模块

七、关键代码解析

7.1 状态管理

Pomo-Board 采用集中式全局状态对象管理所有应用状态:

let state = {
  tasks: [],
  pomodoroCount: 0,
  settings: { ...DEFAULT_SETTINGS },
  timeRemaining: 25 * 60,
  isRunning: false,
  isPaused: false,
  lastTick: null,
  rafId: null
};

所有状态变更后调用 saveToStorage() 持久化,确保刷新页面后数据不丢失。

7.2 requestAnimationFrame 计时精度

使用 requestAnimationFrame 而非 setInterval 的优势:

  • 与浏览器刷新率同步,动画更流畅
  • 页面不可见时自动暂停,节省资源
  • 基于时间戳计算 elapsed,避免累积误差
const tick = (timestamp) => {
  const elapsed = (timestamp - state.lastTick) / 1000;
  state.timeRemaining -= elapsed;
  state.rafId = requestAnimationFrame(tick);
};

7.3 CSS conic-gradient 进度环

进度环的核心实现利用了 CSS 的 conic-gradientmask 属性:

.timer-ring {
  background: conic-gradient(
    var(--accent) 0deg,
    var(--accent) var(--progress, 0deg),
    var(--border) var(--progress, 0deg),
    var(--border) 360deg
  );
  -webkit-mask: radial-gradient(closest-side, white 85%, transparent 85%);
  mask: radial-gradient(closest-side, white 85%, transparent 85%);
}

mask 属性将中心区域挖空,形成环形进度效果。--progress 变量由 JavaScript 动态计算并更新。

7.4 持久化策略

function saveToStorage() {
  localStorage.setItem(STORAGE_KEYS.tasks, JSON.stringify(state.tasks));
  localStorage.setItem(STORAGE_KEYS.count, state.pomodoroCount.toString());
  localStorage.setItem(STORAGE_KEYS.settings, JSON.stringify(state.settings));
}

三个独立的 storage key 分别存储任务列表、番茄计数和设置,便于部分更新和调试。


八、使用场景

  1. 深度工作:开启番茄钟,添加待办任务,专注完成代码编写
  2. 学习备考:设置 45/10 模式,搭配学习任务列表
  3. 日常规划:将每日待办事项添加到任务看板,完成即打勾
  4. 团队协作:无需登录,打开即用,适合快速共享使用
  5. 效率追踪:每日番茄计数记录,追踪自己的专注时长

九、总结

Pomo-Board 是一个功能完备的轻量级番茄钟 + 任务看板工具,它将番茄工作法的核心理念与任务管理完美结合。

其技术实现值得学习:

  • 零框架依赖:纯原生 HTML/CSS/JS 实现,无需构建步骤
  • requestAnimationFrame 计时:高精度、低资源消耗的动画循环
  • CSS conic-gradient 进度环:纯 CSS 实现精美的圆形进度动画
  • Web Audio API 通知:浏览器端合成音效,无需外部资源
  • localStorage 持久化:零后端数据保存,刷新不丢失
  • CSS 自定义属性主题:亮色/暗色模式一键切换
  • 响应式布局:完美适配手机、平板、桌面各种屏幕

如果你正在寻找一个简单好用的番茄钟工具,不妨试试 Pomo-Board!


本文由 Pomo-Board 团队出品,更多信息请访问 Toolion.cn