jQuery / .animate()でアニメーション効果を作る
.animate()は現在のCSS値から目標まで時間をかけて変えます。.animate({ left: 100, width: 160, opacity: 0.4 })なら位置・幅・透明度が同時に変わります。時間とeasingを指定でき、完了は要素ごとに呼びます。
属性と時間を決める
.animate()の最初は目標属性オブジェクトです。数値left・widthはここではpx、opacityは0〜1の単位なしです。同じオブジェクトは同時で、別呼出しが基本列に並ぶのとは異なります。
leftの移動にはstatic以外の配置が必要です。relativeは元の場所からで文書x=100ではありません。widthは内容幅で、border・paddingを単純化しcontent-boxにしました。
durationはミリ秒、既定400です。easingは進行速度でswingとlinearを比べます。同じ目標でも途中が違います。任意の色やtransform文字列まで基本jQueryで補間すると考えず対応数値属性を調べます。
二要素の完全な例
全コードをUTF-8のanimate-demo.htmlに保存し開きます。インターネットから公式完全版4.0.0を読み、effectsが必要なのでslimを避けます。サーバーや導入は不要です。Windows Edge、3.7.1・4.0.0で中間・目標・停止・再生を確認しました。
両方は同じ目標です。Startは既知の初期値に戻し、Resetは時間とeasing選択を保って箱とカウンターを戻します。実行中は重複を防ぎます。
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Animate CSS properties and observe completion</title>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<style>
body { font: 16px/1.6 sans-serif; max-width: 760px; margin: 20px; }
label { display: block; margin: 8px 0; }
select, button { font: inherit; margin: 4px; }
#stage { background: #eef4f4; padding: 10px; overflow-x: auto; }
.box { position: relative; left: 0; width: 80px; height: 45px; margin: 12px 0; background: teal; color: white; box-sizing: content-box; }
pre { white-space: pre-wrap; overflow-wrap: anywhere; }
</style>
</head>
<body>
<label>Duration <select id="duration"><option value="600">600ms</option><option value="1200">1200ms</option><option value="0">0ms</option></select></label>
<label>Easing <select id="easing"><option value="swing">swing</option><option value="linear">linear</option></select></label>
<button type="button" id="start">Start</button>
<button type="button" id="stop">Stop here</button>
<button type="button" id="reset">Reset</button>
<div id="stage"><div class="box" id="alpha">Alpha</div><div class="box" id="beta">Beta</div></div>
<pre id="result" aria-live="polite"></pre>
<script>
jQuery(function ($) {
const $boxes = $("#stage > .box");
let generation = 0, busy = false, state = "ready", completed = 0, batches = 0;
function report() {
const values = $boxes.map(function () {
const $box = $(this);
return this.id + ": left=" + Math.round(parseFloat($box.css("left"))) + "; width=" + Math.round($box.width()) + "; opacity=" + Number(parseFloat($box.css("opacity")).toFixed(2));
}).get();
$("#result").text(["state=" + state, "completed=" + completed + "; batches=" + batches, ...values].join("\n"));
}
function reset() {
generation++; $boxes.stop(true, false).css({ left: 0, width: 80, opacity: 1 });
busy = false; state = "ready"; completed = batches = 0;
$("#start").prop("disabled", false); report();
}
$("#start").on("click", function () {
if (busy) return;
reset(); busy = true; state = "running"; $(this).prop("disabled", true);
const run = generation;
const reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
const duration = reduce ? 0 : Number($("#duration").val());
$boxes.animate({ left: 100, width: 160, opacity: 0.4 }, {
duration: duration, easing: $("#easing").val(),
complete: function () { if (run === generation) { completed++; report(); } }
});
$boxes.promise("fx").done(function () {
if (run !== generation) return;
batches++; busy = false; state = "done";
$("#start").prop("disabled", false); report();
});
report();
});
$("#stop").on("click", function () {
if (!busy) return;
generation++; $boxes.stop(true, false);
busy = false; state = "stopped"; $("#start").prop("disabled", false); report();
});
$("#reset").on("click", reset);
reset();
});
</script>
</body>
</html>
初期幅80、相対left=0、opacity=1です。表示の丸めは計算を整数に限定しません。
state=ready
completed=0; batches=0
alpha: left=0; width=80; opacity=1
beta: left=0; width=80; opacity=1
- 600ms・swingでStart。三属性が同時に変わります。
- 完了はstate=done、completed=2; batches=1で、両方left=100; width=160; opacity=0.4です。
- Reset後easingだけlinearにして比較し、swingへ戻せます。目標は同じです。
- 1200msで開始しStop here。途中でstate=stoppedとなり、後からdoneへ変わりません。
- Reset後再生します。0msなら即目標と完了です。
- 動きを減らすreduceなら1200msを選んでも即時です。
要素別と全体完了
completeは二回でthisは各DOM要素です。最初の一回を全体完了としません。.animate()は終了までJavaScriptを止めません。
.promise("fx")は集合の効果を観察し、ここではbatchesを一度増やしStartを戻します。後に基本列へ追加した処理も待機範囲になり得ます。
列が空でも自然完了とは限りません。.stop(true, false)は途中で止め列を消してもfx promiseが解決し得ます。Stop・Resetは先にgenerationを変え、旧処理がdoneを上書きしないようにします。
連打は通常効果を積むためStart無効とbusyを使います。現在位置から別目標へ変更するUIなら別の中断方針を設計します。
停止・復元と実配置
jumpToEnd=falseは現在値を保ちます。Resetは三属性を明示復元します。中間値を残せば次の比較条件が変わります。
prefers-reduced-motion reduceは今回だけ時間0にし同じ目標と完了経路を使います。全体設定は変えません。
位置と幅は周囲や重なりに影響するため、狭い画面、拡大、長文、スクロール領域を確認します。opacity=0も自動でdisplay:noneやアクセシビリティ上の非表示にはならず別途設計します。
CSS transitionやプラグインが同じ属性を同時制御しないよう、対象と属性・列の所有を定め、選択子とイベントを機能内へ限定します。




