main
Broken Time — Roman Clock
一块停摆的罗马钟,等待一记敲击。 指针仍在转动,表盘已经碎裂;时间在裂缝之间流淌。
Broken Time 是一款纯浏览器交互式罗马时钟。点击表盘将其击碎,碎片带着泛光四散飘落;再点击任何一块碎片,还能继续把它砸得更碎——直到每一块都小得无法再碰。时间指针始终运转,透过层层裂缝,隐约可见背后如星屑般散落的诗句。
v0.7.3 — struck
特性
- 罗马数字表盘:XII · I · II · III · IV · V · VI · VII · VIII · IX · X · XI,环绕 60 格分钟刻度(整点刻度加粗加长)
- 实时走时:时、分、秒三针按真实时间平滑运转;秒针以暖金色区别于银白双针,双层描边模拟指针泛光
- 击碎交互:点击表盘触发扩散打击环动画,表盘按点击点呈扇形碎裂为 5 块多边形碎片
- 递归粉碎:任意碎片可被再次击碎,射线切割、锯齿裂边,越碎越小,直到面积过小无法继续
- 诗意文字碎片:表盘背后密布 40+ 条与时间、破碎、记忆、死亡相关的诗句,随碎裂逐层显现
- 碎片物理:初速度、角速度、空气阻尼衰减、面积加权的碰撞分离,破裂边缘带三层泛光消散
- 复古拟物细节:自定义指针光标、BSOD 风格四角角标、逐字呼吸的提示语、
Reform Time复原按钮
使用方法
用任意现代浏览器打开 BrokenClock.html 即可,无需构建、无需安装、无外部运行时依赖(仅 Google Fonts 字体为网络加载,缺失时自动回退到衬线字体)。
| 操作 | 效果 |
|---|---|
| 点击完整表盘 | 击碎时钟,碎片飞散 |
| 点击碎片 | 继续粉碎该碎片 |
点击 Reform Time |
恢复完整表盘 |
交互设计
- 打击感:每次敲击都有一个约 130ms 的打击环动画——双层同心圆扩散、透明度与线宽同步衰减,随后碎片才开始崩解,先声后效,节奏分明
- 碎片排序:初次碎裂时 5 块碎片按面积降序排列,第二大的一块被标记为「文字碎片」,承载诗句贴图,保证诗意的最高可见度
- 越碎越慢:碎片初速度按序号递增缩放(
speedFactor = 0.4 + i * 0.1),整体呈扇形展开,避免一拥而散 - 弹性碰撞:相邻碎片按面积比例互相推挤(质量正比于面积),并施加极小速度分离项,防止碎片粘连
技术实现
渲染架构
- 纯原生 JavaScript + Canvas 2D,单文件、零依赖
- 三层画布分离:
clockCanvas(离屏):完整表盘静态层——罗马数字、刻度、指针,每帧重绘textCanvas(离屏):诗句层,按表盘圆形区域以螺旋式行排布,仅窗口缩放时重绘(textDirty标记)- 主
canvas:交互合成层,负责碎片变换、碰撞、打击效果
- 碎片绘制时
save → translate → rotate → translate → clip → drawImage,将对应离屏贴图按碎片自身变换裁剪映射,实现「破碎表盘」视觉
碎裂算法
- 初次碎裂:以点击点为公共顶点,按随机加权区间(
0.6 + random * 1.4)将圆周角切成 5 个扇形,每个扇形的两段半径用zigzagPath加锯齿扰动,外弧用 30 段离散点逼近 - 递归碎裂:对目标碎片发射 3–4 条随机射线,用
rayPolygonIntersect求射线与多边形边的首个交点(t > 1e-6, u ∈ [0,1]的最近者),按交点角度排序后依次连接成新的子多边形,面积小于 50 的碎屑直接丢弃 - 顶点数据:每个碎片携带局部坐标系下的多边形点集、质心、面积、等效半径
√(area/π)、线速度、角速度,旋转时通过pointToScreen / pointToLocal双向换算命中检测
物理与效果
- 运动积分:每帧
offset += v、rotation += ω,速度阻尼v *= 0.95、角速度阻尼ω *= 0.97,碎片逐渐静止 - 碰撞解析:O(n²) 对撞检测,基于等效半径的软球模型,按面积加权分配推挤位移,模拟质量差异
- 泛光模拟:刻意规避
shadowBlur(性能黑洞),改用三层描边叠加——外层粗线低透明度模拟弥散、中层中等粗细做光晕、内层细线高透明度做核心高亮,透明度随碎片诞生后 1.5s 内指数衰减 - 指针泛光:同样以双层描边(宽晕 + 细芯)替代 shadow
关键函数
| 函数 | 职责 |
|---|---|
drawClockTo(c) |
表盘静态层渲染:罗马数字、刻度、三针 |
drawTextShardTo(c) |
诗句层渲染:按圆截面逐行布字 |
shatterInitial(x, y) |
初次扇形碎裂 |
shatterShard(shard, x, y) |
递归射线切割 |
rayPolygonIntersect(...) |
射线与多边形求交(切割 + 命中) |
zigzagPath(...) |
锯齿化破裂边线 |
resolveCollisions() |
面积加权碰撞分离 |
pointToScreen / pointToLocal |
碎片局部/世界坐标换算 |
文件结构
BrokenClock/
└── BrokenClock.html # 全部实现,单文件即完整应用
主题与彩蛋
- 四角角标致敬 Windows BSOD:
0x0000007B、SESSION: FRAGMENTED、ROMAN.PROTOCOL // XII - 诗句取材于时间的辩证:
Time is the fire in which we burn.、Memento mori.、Tempus edax rerum、And in the end, the clock was always already broken. - 字体三件套:
Cinzel(罗马铭文体)、EB Garamond(诗句衬线体)、Special Elite(打字机角标体) - 光标是一支 SVG 手绘的敲击锤,命中即锤落
Strike the dial — shatter the lie — free the hour.
Description
The hands are still turning, but the clock face is already shattered; time flows through the cracks.
50 KiB
0 Stars
1 Watchers
0 Forks
Languages
HTML
100%