动画引擎原理 总览待审核
galton · 预定关键帧路径 · 交错投放

高尔顿钉板:把随机过程塞进确定性播放器

小球从顶部落下,每撞一排钉子就左右各半概率偏一格,穿过 N 排后落入底部某个槽——大量小球累积出二项分布, 随排数增大逼近正态曲线。它看似是一台需要碰撞检测的物理玩具,但落点其实只取决于「这一路向左还是向右」的一串随机抉择; 抉择一旦抽定,整条下落轨迹就是一条确定的折线

于是它正好印证本系列的一条主线:把随机性收进「开局抽一次路径」,播放本身仍是 时间 → 值的纯函数。每个球是一个 Animation:keyframes 是它预抽好的路径, onUpdate(p) 沿折线采样位置,sink 换成 canvas 画几十个球同时下落; 交错投放形成持续的「倾泻」。因为是纯函数,单球可任意 seek、可反向(见下)。

连续投放:钟形分布自己长出来

持续向钉板倾泻小球,底部直方图实时累积。拖动偏置 p 让左右概率不再对半,分布随之偏斜、整体均值移到 N·p; 叠加的细线是对应的理论二项分布。排数越多,堆出的形状越贴近正态。

已投 0 峰值槽 实测均值 理论均值 N·p =
随机只发生一次,在「抽路径」那一刻:每个球开局抽好一串左右抉择 dirs,之后的下落是对一条 确定折线的采样。所以这台「物理玩具」无需任何碰撞检测或逐帧随机——它和弹簧、关键帧一样,是 currentTime → 位置 的纯函数,因此可暂停、可 seek、可反向。直方图的钟形不是某个球的属性, 而是大量独立 dirs统计涌现

单球可回退:路径是预先抽好的关键帧

把镜头收到一个球上。它的整条轨迹由开局那串 dirs(下方,L 向左 / R 向右)唯一决定,已画成淡色折线。拖动播放头可在轨迹上任意 scrub,点反向让它倒着爬回顶部——位置只是 currentTime 的函数,回退零成本。点重抽路径换一串 抉择,落点随之改变。

落入槽 (= dirs 中 R 的个数);同一串 dirs 无论正放 / 反放 / scrub,轨迹完全一致。

@vega/anim — 每个球 = 一个 Animation,keyframes 是预抽的路径

  
二项 → 正态:每排是一次独立的 ±1 伯努利试验,落点是 N 次之和,故服从二项分布 B(N, p);由中心极限定理, N 增大时逼近正态,均值 N·p、方差 N·p(1−p)。这与噪声三角函数同属「非补间的信号源」——只是这里的信号是一串离散随机抉择,而非连续的周期或噪声。