《晚霞专注钟》:一个单文件网页番茄钟的设计与实现

举报
桑田 发表于 2026/10/29 23:56:29 2026/10/29
【摘要】 一个不催人的网页番茄钟:用 CSS 渐变画出一片黄昏,让太阳随专注进度缓缓下沉;单 HTML 文件实现三档计时与按天完成计数,附核心代码拆解。

番茄钟工具多如牛毛,但大多数都在「催」人:红色的倒计时、刺耳的提示音、超时未完成的负罪感。我想反着来——做一个不催人的专注计时器:整个页面是一片黄昏,计时开始后,一轮太阳随着进度缓缓下沉;时间走完,太阳正好沉到地平线附近,抬头就是晚霞。这个小作品叫《晚霞专注钟》,已经发布在华为云开发者作品展览馆,源码开源在 GitHub(sangtiandetian/dusk-focus-clock),全文只有一个 HTML 文件,无框架、无图片资源、无构建步骤,浏览器打开就能用。

一、设计:一片 CSS 画出来的黄昏

页面背景是一条五段的线性渐变,从深紫到橙红,模拟黄昏时天空的层次:

background: linear-gradient(180deg, #2b1055 0%, #7597de 30%, #ff9a76 62%, #ff6b6b 82%, #845ec2 100%);

太阳是一个 150px 的 div,圆形、径向渐变,再加一层大范围的 box-shadow 做光晕:

.sun {
  width: 150px; height: 150px; border-radius: 50%;
  background: radial-gradient(circle, #ffd93d 0%, #ff9a3d 70%, #ff7b3d 100%);
  box-shadow: 0 0 80px 30px rgba(255, 170, 60, .45);
}

不引用任何图片,整个「场景」就是渐变加几何图形,文件小、加载快,也天然适配任何屏幕。

二、核心机制:让太阳跟着进度下沉

关键只有一行进度计算:p = 1 - left / total,其中 left 是剩余秒数、total 是本轮总秒数。每秒 tick 时,把 p 映射为太阳的位移和缩放:

function render() {
  clock.textContent = fmt(left);
  var p = 1 - left / total;
  sun.style.transform = 'translateY(' + (p * 46) + 'px) scale(' + (1 - p * 0.12) + ')';
}

太阳最多下沉 46px、同时缩小到 88%,配合 CSS 里给 .sun 设置的 transition: transform 1s ease,每一秒的移动都是平滑滑动而不是跳格。这样时间进度就变成了一个不用读数字也能感知的视觉信号:瞥一眼太阳的高度,就知道这一轮走到哪了。

三、时长档位与完成计数

页面提供三档:专注 25 分钟、专注 15 分钟、休息 5 分钟,按钮上用 data-min 存分钟数,点击时切换 total 并重置状态,不用为每档写一份逻辑。

完成次数按天统计,用 localStorage 存,键名里直接拼上日期字符串:

var KEY = 'dusk-focus-' + new Date().toDateString();
done = parseInt(localStorage.getItem(KEY) || '0', 10);

跨天之后键名自动变化,计数天然清零,不需要写任何「每日重置」的定时逻辑。另外有个小规则:只有 15 分钟以上的专注轮次才计次,5 分钟休息走完不计数,避免把休息也刷成「成果」。

四、两个实现细节

一是数字不跳动:倒计时用 font-variant-numeric: tabular-nums,让每一位数字等宽,25:00 变成 24:59 时整串文字不会左右抖动。

二是先承认 setInterval 的漂移:setInterval(fn, 1000) 在页面切到后台时会被浏览器节流,长时间计时会有误差。这个小工具单轮最长 25 分钟、且切后台通常意味着人已经离开,我接受了这个误差;如果要做严谨的计时,应该改成记录结束时间戳、每 tick 用 Date.now() 反推剩余时间,漂移就不存在了——这也是下一版准备改的点。

五、小结

《晚霞专注钟》的全部逻辑不到一百行 JavaScript,它想验证的事情很简单:计时器不一定要用进度条和百分比,把进度翻译成一个自然现象——日落——专注的过程就安静下来了。作品已发布在华为云开发者作品展览馆(作品名:《晚霞专注钟》),源码在 GitHub 仓库 sangtiandetian/dusk-focus-clock,欢迎试用和提 Issue。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。