- `fadeIn()`と`slideUp()`は魔法ではなく「数値の更新ループ」
- `fadeIn()`の内部動作
- `slideUp()`の内部動作
- なぜCSSアニメーションではないのか
- イージングの仕組み
- アニメーション中に起きていること
- `stop()`が必要になる理由
- なぜカクつくのか
- 現代との違い
- 最後に
`fadeIn()`と`slideUp()`は魔法ではなく「数値の更新ループ」
jQueryのアニメーションは特別な描画機能を使っているわけではありません。
実体はとてもシンプルで、一定間隔でCSSの数値を書き換え続けているだけです。
「アニメーションしている」ように見えるのは、
ブラウザが連続する小さな変化を人間の目に滑らかに見せているからです。
つまり`fadeIn()`も`slideUp()`も、GPUや動画のような処理ではありません。
JavaScriptによる繰り返し処理です。
`fadeIn()`の内部動作
次のコードです。
$("#box").fadeIn(400);
何が起きているかというと、opacity(透明度)を0から1まで徐々に変更しています。
内部では概ね次の流れになります。
1 displayを復元
2 opacityを0に設定
3 タイマー開始
4 数ミリ秒ごとにopacityを増加
5 1になったら終了
擬似コードにするとこうです。
let opacity = 0; const timer = setInterval(function(){ opacity += 0.05; element.style.opacity = opacity; if(opacity >= 1) clearInterval(timer); }, 13);
13msという数字は約60fps(1秒60回更新)を狙った値です。
つまり`fadeIn()`は手動でフレーム更新している処理です。
`slideUp()`の内部動作
次は`slideUp()`です。
$("#panel").slideUp(400);
これは高さ(height)を徐々に小さくしています。
しかし単純にheightだけを変更しているわけではありません。
実際には以下を調整しています。
- height
- padding-top
- padding-bottom
- margin-top
- margin-bottom
- overflow
理由は、要素の見た目を自然に縮めるためです。
高さだけ0にすると中身がはみ出します。
処理のイメージ:
1 現在の高さを取得
2 overflow:hidden設定
3 高さを徐々に減らす
4 最後にdisplay:none
つまり`slideUp()`は「高さアニメーション+非表示化」です。
なぜCSSアニメーションではないのか
現在なら次のように書けます。
.box{ transition: opacity .4s; }
ではなぜjQueryはJavaScriptでやっているのでしょうか。
理由は、jQueryが作られた当時はCSSアニメーションが存在しなかったからです。
古いブラウザには
- transition
- animation
- transform
がありませんでした。
つまりjQueryは、CSSにない機能をJavaScriptで再現したライブラリだったのです。
イージングの仕組み
jQueryのアニメーションには「swing」「linear」があります。
$("#box").fadeIn(400, "swing");
これは速度を変化させています。
実際には時間経過に対して変化量を計算しています。
線形:
毎フレーム同じ量だけ変化
スイング:
最初ゆっくり → 中央速い → 最後ゆっくり
数学的には、時間tに対して進行率を関数で変換しています。
これも毎フレーム計算されます。
アニメーション中に起きていること
ここが重要です。
アニメーション中、ブラウザは毎フレーム次を行います。
- JavaScript実行
- スタイル変更
- 再計算
- 再描画
つまり400msのアニメーションなら、数十回の描画更新が発生します。
これが負荷になります。
`stop()`が必要になる理由
次のコードを連続クリックするとどうなるでしょう。
$("#menu").slideToggle();
クリックのたびにアニメーションが積み重なります。
jQueryはアニメーションキューを持つためです。
結果:
- 遅延して動く
- 数秒後に動く
- カクつく
これを防ぐのが`stop()`です。
$("#menu").stop(true,true).slideToggle();
キューをクリアし、現在のアニメーションを終了させます。
なぜカクつくのか
jQueryアニメーションが重くなる理由は明確です。
レイアウトに影響するプロパティを毎フレーム変更しているためです。
特に重いもの:
- height
- width
- top
- left
これらはレイアウト再計算(reflow)を発生させます。
一方、軽いもの:
- opacity
- transform
これはレイアウトを変えません。
現代との違い
現在の推奨はCSSやrequestAnimationFrameです。
ブラウザがフレームタイミングを最適化します。
jQueryはsetIntervalベースでした。
そのため描画タイミングと同期せず、無駄な再描画が起きることがあります。
最後に
`fadeIn()`や`slideUp()`は高度なアニメーションエンジンではありません。
JavaScriptでスタイルを少しずつ書き換える「疑似アニメーション」です。
当時としては画期的でしたが、
現在のブラウザではより効率的な方法が用意されています。
それでもjQueryのアニメーションを理解すると、
Webの表示が「絵」ではなく「計算結果」であることがよく分かります。