最近、なかなか面白い小実験をやってみました。
二次元キャラクターのちょっとしたアニメーション効果を、それぞれ:

  • WebGL
  • Canvas 2D
  • 純 DOM + CSS

の3つの方法で実装し直しました。
効果自体は複雑ではありません:

  • まばたき
  • 眉毛/下まぶたの連動
  • 汗のゆらゆらした揺れ
  • アホ毛の振り動き

でも本当に面白いのは、「作れた」こと自体ではなく:

同じものを、3つの技術スタックで実装したとき、どれくらい差が出るのか?

というところです。
本質的には「フロントエンドグラフィクス色の濃い」再現実験でした。


最初はただアホ毛アニメーションを再現したかった

インスピレーション元:https://tamanidamani.itch.io/nijikas-ahoge
当時のシンプルな思い:「自分だったらどう実装する?」
そしてやるほどに熱中してしまい、最終的にこうなりました:

じゃあ、WebGL、Canvas2D、DOM の3パターン全部作ってみよう。

そうしてリポジトリは今の形になりました:

同じ効果を3つのバージョンで実装しています。


まず結論

一言でまとめるなら:

WebGL が最強だけど、Canvas2D が一番書きやすくて、DOM がビジネス向け


1. WebGL バージョン:「本当のゲーム開発」に一番近い

このバージョンが一番手間がかかります。
なぜなら本質的には「フロントエンドアニメーション」ではなく:GPU グラフィクスプログラミング だからです。


どう実装しているのか?

コアとなる考え方は:

  • 背景レイヤー1枚
  • スプライトを重ねていく
  • shader で描画制御
  • JS でアニメーションパラメータを動かす

例えば:

  • アホ毛の回転
  • まばたきの切り抜き
  • alpha ブレンド

これらはすべて GPU 側で処理されます。
だんだんとこういうものに触れるようになります:

  • uniform
  • texture
  • shader
  • UV
  • 頂点座標
  • テクスチャ座標

そして笑顔が消えていきます。


でも WebGL は本当に強い

要素が増えてくると、WebGL の「全然平気」という感覚が際立ちます。
特に:

  • 高解像度
  • マルチレイヤー
  • shader エフェクト
  • パーティクル
  • ポストプロセス

こういう場面では、
Canvas2D は息を切らし始め、
DOM はカクカクになり始めます。
WebGL はまだ平然と:「もっと来い」と言わんばかりです。


でも開発体験は……

正直に言えば:かなりハードコアです。
「なぜテクスチャが反転してるの?」というだけでも30分調べることになります。
なぜなら:

  • 座標系が違う
  • UV の向きが違う
  • テクスチャの原点が違う

さらには:shader の変数名を1つ間違えると画面が真っ暗になる。 コンソールには人間の読める言葉ひとつ出ません。


2. Canvas2D:一番書いていて気持ちいいバージョン

ここは:「複雑さがちょうどいい」 ところです。

drawImage は本当に神器

このバージョンのコアは基本的に: ctx.drawImage(...)
ひたすら描いて、重ねて、切り抜くだけ。


まばたきはどう実装する?

ここはかなり気に入っています。
単純にスケールするのではなく:ソース画像を上から下へ切り抜いていく。 そして下端を固定。
こうすることで、単なる画像圧縮ではなく、本当の「目を閉じる」ように見えます。
こういう小さなディテールが、見た目の印象を大きく変えます。


アホ毛はどうやる?

Canvas2D での回転は非常にオーソドックス:

save()
translate()
rotate()
drawImage()
restore()

左下の支点を中心に回転。
おしまい。 考え方が非常に直感的です。


なぜ Canvas2D がスイートスポットだと思うか

「効果も出せるし、髪も抜けない」 というバランス感覚があるからです。
WebGL のように:「アニメーションを作る前に shader に教えられる」こともありません。
でも DOM のように:「後半はブラウザのレイアウトシステムと格闘する」こともありません。
Canvas2D は基本的に:

  • デバッグしやすい
  • ブラウザ互換性が高い
  • 思考の負担が小さい
  • 十分な自由度がある

だからこそ、多くのインディーゲームが好んで使うのも納得です。


3. DOM バージョン:「グラフィクスプログラミング」らしくないバージョン

このバージョンは実は一番面白いです。
canvas に一切頼らず、純粋に:

  • HTML
  • CSS
  • JS

だけで作っています。


パーツは全部 div

例えば:

  • 眉毛

これらはすべて <div> で、

  • background-position
  • background-size

を使ってアトラスから切り抜いています。


目を閉じる実装は UI テクニックっぽい

このアプローチは自分でもかなり気に入っています。
overflow: hidden; でマスクを作り、
中のスプライトを下に動かすことで「上から下へ目を閉じる」を実現しています。


DOM の最大のメリット

本当のウェブページ に適しています。
例えば:

  • UI システム
  • ボタン
  • テキスト
  • レスポンシブレイアウト

これらとシームレスに融合できます。


でも DOM は確実に重くなる

特に要素が増えると:

  • layout
  • repaint
  • composite

ブラウザが猛烈に再計算を始めます。
気づけば:CSS でゲームエンジンの半分を作っている自分 がいます。


3つの方案、結局どう選ぶ?

「どれがどれを圧倒する」というものではありません。
あるのは:今のプロジェクトが何に近いか だけです。

もしあなたが:

  • 複雑なビジュアルエフェクトを作りたい → WebGL
  • インディーゲームを作りたい → Canvas2D
  • ウェブページ上でインタラクティブなキャラクターを作りたい → DOM

このプロジェクトで一番感じたこと

実は、異なる技術スタックの背景には、
まったく異なるレンダリングの思考法があります。

  • WebGL は考える:GPU がどう描くか
  • Canvas2D は考える:このフレームをどう描くか
  • DOM は考える:ブラウザがどうレイアウト・合成するか

これらは同じ世界観すら違います。


おわりに

このリポジトリの本質は「アニメーションを作る」ことではなく、
実は次のことを研究するものでした:

ブラウザは一体どうやってものを画面に描いているのか。

コードと一緒に読むのがおすすめです:https://github.com/iAJue/CanvasGame

前回こんな比較をしたのはもう前回の話です:《如何优雅的提交一个表单》
图 91