JS で自作するトゥイーン

GSAP / anime.js / motion などのライブラリを使う前に、「中で何が起きているか」を理解する。 rAF + 補間 + イージング の 3 点セットだけで、トゥイーン / キーフレーム / タイムライン / スプリングまで組める。

このノートの目的

アニメーションの正体

画面上でなめらかに動いて見えるのは、毎フレーム少しずつ値を変えて描き直しているだけ。 コアは次の 3 つに集約される。

   時間 (t)
   ──────────────────▶
0% ────────────────── 100%

[1] 0〜1 に正規化       (経過時間 / 全体時間)
[2] イージングで歪める  (linear / easeOutQuad / etc)
[3] 値を補間            (lerp(start, end, t))
[4] 適用               (element.style.transform = ...)
      

30 行のミニ実装

ライブラリを使わず、requestAnimationFrame + lerp + イージングで動くトゥイーン:

function tween({ from, to, duration, easing = (t) => t, onUpdate }) {
  return new Promise((resolve) => {
    const start = performance.now()
    function frame(now) {
      const t = Math.min((now - start) / duration, 1)
      const eased = easing(t)
      const value = from + (to - from) * eased
      onUpdate(value)
      if (t < 1) requestAnimationFrame(frame)
      else resolve()
    }
    requestAnimationFrame(frame)
  })
}

// 使い方
const box = document.querySelector("#box")
await tween({
  from: 0, to: 300, duration: 800,
  easing: (t) => 1 - Math.pow(1 - t, 3),  // easeOutCubic
  onUpdate: (x) => {
    box.style.transform = `translateX(${x}px)`
  }
})

これが世のすべてのトゥイーンの最小核。あとはこれを「複数値同時」「複数アニメーション直列」 「逆再生 / ループ / 一時停止」… と拡張していくだけ。

用語の整理

用語意味
Tween2 値の間(between)を補間して動かす単位
Keyframe時間軸上の複数の「節」となる値
Easing0〜1 の進行を歪める関数(緩急をつける)
Interpolation2 値の中間を求める計算(lerp / spline / 球面)
Timeline複数のトゥイーンを時系列に並べる仕組み
Springバネと減衰の物理シミュレーション。時間ベースでない
Delta time (dt)前フレームからの経過時間(秒 / ms)
Easing function例: easeInOutCubic, easeOutBack

このセクションの読み方

  1. requestAnimationFrame — 時間管理の基礎
  2. 補間 — 線形・カラー・配列・角度
  3. イージング関数 — 30 種類の実装と使い分け
  4. Tween クラス自作 — Promise / chaining / 制御
  5. キーフレーム — 多段・スプライン・パス
  6. タイムライン — 直列・並列・スクラブ
  7. スプリング — バネの物理
  8. 最適化と注意点 — 60fps を守る

ライブラリと自作の使い分け

状況選択
とにかく早く・複雑な演出GSAP / motion / anime.js
React で宣言的framer-motion / @react-spring
CSS で済むCSS Transitions / Animations / WAAPI
Three.js / Canvas / WebGL の中自作の方が綺麗(ループに統合できる)
軽量さ・依存ゼロ自作(数十行で済む)
学習目的自作

本ノートで作るもの(最終形)

ブラウザ標準も知っておく

簡単な演出なら CSS / WAAPI で十分。複雑な演出Canvas / WebGLでは JS で自前ループを回す方が綺麗にまとまる。

最短ルート

まず requestAnimationFrame線形補間 を一回手書きする。 そこから先は知識の積み重ねでしかない。