我给网站塞了一只会开枪的螃蟹
事情是这样的。
朋友发了个链接——pretext,一个不碰 DOM 就能量文本布局的库。我点进 demo 看了一眼。
十万个文字方块在做瀑布流排版,120fps。文字绕着移动的障碍物实时排版。一个人的物理引擎让每个字符变成粒子,点哪里哪里爆炸。
我看着自己那个终端风格的作品集网站,脑子里只有一个念头:
如果我的文字也能炸呢?
六个小时后,两个网站都有了粒子物理、弹跳子弹、和一只会射击的动画像素螃蟹。
终端网站:文字就是一切
我的作品集 xiax.xyz 是一个 macOS 终端模拟器——纯 vanilla JS,零依赖。文字就是整个界面。这让它成了做文字特效的完美场地。
切换标签页的时候,文字炸了
你点一个新标签页,屏幕上每个可见字符都变成一个物理粒子。它们从点击位置向外散射——用的是反平方力(和真实爆炸一样),加上重力、空气阻力、旋转。每个粒子飞着飞着就淡出了。
物理公式很简单,但手感很好:
力 = 爆炸常数 / 距离²
速度 *= 空气阻力 // 每帧 × 0.965
速度.y += 重力 × dt // 580 像素/秒²
爆炸结束后,终端的打字机效果继续一个字一个字敲出新标签的内容。爆炸是戏剧性的退场,打字是从容的登场。节奏感。
Clawd:会开机枪的像素螃蟹
然后事情就变得好玩了。
我找到了 clawd-tank——一个全是 Claude 吉祥物(螃蟹)动画 SVG 的仓库。走路动画纯 CSS 关键帧:身体上下晃,腿交替迈步,钳子摆动,眼睛眨巴。一共 24 种动画,打字的、睡觉的、丢球的都有。
交互流程:
- 在终端区域双击 → 螃蟹出现,鼠标消失
- 移动鼠标 → 螃蟹跟随,朝移动方向转身(完整 360 度)
- 长按鼠标 → 朝面对的方向扫射子弹
- 按得越久 → 射速从 6 发/秒飙到 40 发/秒,散布角越来越大
- 子弹打到字符 → 字符获得速度冲量,被推飞
- 子弹打到墙壁 → 弹跳,保留 55% 能量,继续乱弹打字
- 松开鼠标 → 字符靠弹簧物理缓缓回到原位
- 鼠标移出或按 Escape → 螃蟹淡出,一切恢复
字符回弹的物理用的是弹簧-阻尼模型:
速度 += (家 - 当前位置) × 弹力系数
速度 *= 阻尼
位置 += 速度
字符在原位置附近振荡然后自然稳定。整个过程 60fps,零 reflow,因为都在 Canvas 上渲染。
搬到博客:翻车了
博客 nlog.xiax.xyz 跑的是 Next.js——比终端的单容器 vanilla JS 复杂太多了。移植 Clawd 教会我一个深刻的教训:
从简单布局提取文字到 Canvas 上可以。从复杂页面提取,必翻车。
终端是单个可滚动 div 里的等宽文字,不重叠。博客有 sticky 头部、折叠的 <details> 元素、absolute 定位的 UI、可变字体、多个 z 层级。把所有文字平铺到一个 Canvas 上,结果就是一团糊——文字叠在一起,乱得没法看。
我试了 visibility: hidden —— 失败,CSS 优先级问题。
试了 opacity: 0 —— 失败,Canvas 也是 body 的子元素,一起隐了。
试了 color: transparent —— 失败,图片、边框、背景色都还在。
把 Canvas 挂到 <html> 上 —— 好一点,但文字还是重叠。
四种方案,四次翻车。
顿悟:别在 Canvas 上画文字
最后的方案完全换了思路:
- Canvas 是透明的 —— 只画子弹粒子(橙色小点)
- Clawd 是一个 fixed 定位的
<img>—— CSS 动画原生播放 - 子弹打到 DOM 元素时,用 CSS transform 推开它们
- 元素自动弹回
也就是说,页面始终是浏览器正常渲染的。链接能点。图片能看。布局是对的。螃蟹和子弹只是一层叠加在上面的视觉效果,冲击波在真实的 DOM 里荡漾。
简单。暴力。有效。
博客上的全部特效
除了 Clawd 之外,博客还有 6 个彩蛋:
| 特效 | 触发方式 |
|---|---|
| Clawd 机枪螃蟹 | 任何页面双击 |
| 文章卡片爆炸 | 点击首页的文章 → 卡片文字炸开,然后跳转 |
| 标签云物理 | 点一个标签 → 其他标签弹射散开 |
| 代码块爆炸 | 双击代码块 → 字符炸开然后重组 |
| 阅读奖励 | 滚到文章最底部 → 五彩纸屑爆发 |
| 科乐美密码 | ↑↑↓↓←→←→BA → 永久 Clawd 模式(跨页面保持) |
所有特效用 dynamic import 避免 SSR 问题,尊重 prefers-reduced-motion 设置,加载失败也不影响正常浏览。
Claude Code 实际写了什么
整个特效引擎——900 多行 Canvas 物理、字符提取、粒子系统、Clawd 交互——是 Claude Code 在一个 session 里写的。
最难的部分不是物理(那些是经典算法)。最难的是浏览器集成:Canvas 定位、隐藏元素上的事件代理、移动端触摸事件协调、以及博客上那场史诗级的 DOM 隐藏战争。
总计:两个网站 2000 多行新代码,10 多个文件的修改。
有些东西,人来写可能要一周。让 AI 写,核心障碍从「实现量」变成了「判断力」——什么时候该换方案,什么时候该止损。
四次翻车之后决定完全不画文字,就是那个判断。
去玩
终端网站:xiax.xyz,在终端区域双击。移动鼠标。长按射击。拖动瞄准。看子弹弹。
博客:nlog.xiax.xyz,任何页面双击。子弹会推开真实的 DOM 元素。
科乐美密码:在博客任意页面按 ↑↑↓↓←→←→BA。螃蟹永驻。跨页面不消失。
特效引擎源码:terminal-site/effects.js。螃蟹 SVG 来自 clawd-tank。灵感来自 pretext 和 pretext-explosive。