skip to content

Kros Dai

about

  • a father
  • like coding
  • presently as ceo of TapTap, co-founder of XD Inc
  • previously as co-founder of VeryCD

posts

notes

  • 给 notes 加交互:三层组件约定

    从这篇起,notes 不再只是纯文字。站点按「表现复杂度」分三层来承载交互,够用就停在最轻的一层——越往下,JS 成本越高。三层都遵守同一套主题契约:跟着 data-theme 变色、尊重 prefers-reduced-motion、带无障碍标注。

    第 1 层 · animated-SVG(零 JS)

    几何、坐标、元素有限的图——首选这一层。矢量缩放无损,颜色用 currentColorvar(--color-accent) 等语义 token,所以切换明暗主题时零 JS 自动变色;动画用纯 CSS,在系统「减少动态效果」时自动静止。试试右上角切主题,下图的轨道与圆点会跟着换色:

    三层轨道示意 围绕中心节点旋转的三条同心轨道,演示零 JS 随主题变色的矢量动画。
    三条同心轨道绕中心匀速自转——纯 CSS 动画,切主题零 JS 变色。

    第 2 层 · Canvas + JS

    大量点、连续曲线、需要逐帧重算的图(波形、粒子、实时模拟)——SVG 节点会爆炸,改用 Canvas。代价是 Canvas 不会自动变色:得用 getComputedStyle 取 CSS 变量、用 MutationObserver 监听 data-theme 重新取色重画,并做 devicePixelRatio 适配。下图是两条叠加正弦波,切主题时会重新取色:

    随主题变色的叠加波形动画
    两条叠加正弦波逐帧重算;离屏自动暂停、reduced-motion 下只画一帧静态。

    第 3 层 · React 19 island

    多个输入互相联动、状态驱动的实时重算、需要图表库或较深组件树——才升到 React。它在 MDX 里以 client:visible 注水,进入视口才加载 JS。下面这个复利小工具拖动任一滑块,数值与增长条会实时联动(刻意不引图表库,纯 state + 内联条形):

    1,000
    5%
    10 年

    10 年后:1,629

    收益 +62963%)

    怎么选

    • 能用 SVG 就别用 Canvas:零运行时、自动变色、可访问性最好。
    • 点数多到 SVG 卡,或要逐帧动画 → Canvas,但得自己接主题与 DPR。
    • 真要状态联动 / 图表库 / 深组件树 → React,默认 client:visible

    三层的完整约定(目录、主题联动规则、client:* 默认、a11y、import 路径)写在仓库 AGENTS.md 的「交互组件分层约定」一节,也是自动化生成 note 时遵循的规范。