🧮

Remotionコード分析 — spring()物理エンジンの内部実装

減衰スプリング微分方程式をJavaScriptでシミュレーションするspring()の数学とコード

GitHub: remotion-dev/remotion/packages/core/src/spring

spring()の滑らかなバウンスの秘密は減衰調和振動子の方程式: m*x'' + c*x' + k*x = 0。

判別式 D=c²-4mk が3種類の解を決定: overdamped(バウンスなし)、critically damped(最速収束)、underdamped(バウンスあり)。zeta比 damping/(2*sqrt(stiffness*mass)) がどのパスを選ぶか決定します。

measureSpring()は値が1の閾値内に収まるまでイテレーションしてスプリングアニメーションの持続フレーム数を事前計算します。

動作フロー

1

spring({frame, fps})がframe/fpsで時間(秒)を計算

2

zeta = damping / (2 * sqrt(stiffness * mass))で減衰比を計算

3

zeta < 1ならunderdamped: exp(-ζω₀t) * cos(ωDt)の解 → バウンスアニメーション

4

zeta ≥ 1ならoverdamped/critically damped: バウンスなしで1に収束

5

measureSpring()で|1-value| < 0.001になるフレームを見つけてdurationInFramesを決定

メリット

  • 実際の物理学: CSS ease-in-outのような任意の曲線ではなく、物理法則に基づく自然なモーション
  • 決定的: 同じframeに常に同じ値、数式なので100%再現可能
  • measureSpring()でduration自動計算 → ハードコーディングなしで適切な長さを決定

デメリット

  • 数学的理解が必要: 減衰比/固有振動数の概念を知らないとconfigチューニングが試行錯誤

ユースケース

spring configチューニング: mass/damping/stiffness値がビジュアル的にどんな効果か数学的に理解 カスタムイージング関数の実装: spring()のパターンを参考に独自の物理シミュレーションを制作