JavaScript Web Animations API:滑らかに動く UI を設計するための基本と実践
Web アプリケーションにおいて、滑らかで心地よいアニメーションは、ユーザー体験を大きく向上させる重要な要素です。従来、JavaScript でアニメーションを実装する場合、CSS アニメーションや jQuery、あるいは requestAnimationFrame を使った独自実装など、さまざまな方法が混在していました。
しかし、Web Animations API(WAAPI)の登場により、JavaScript からアニメーションを直接制御できる標準的な手段が提供されるようになりました。この API は CSS アニメーションのパフォーマンスと、JavaScript の柔軟な制御を兼ね備えた、まさに「いいとこ取り」の技術なのです。本記事では、Web Animations API の基本から実践的な使い方まで、初心者の方にもわかりやすく解説していきますね。
背景
Web アニメーション実装の歴史
Web 開発におけるアニメーション実装は、時代とともに進化してきました。初期の Web サイトでは GIF アニメーションや Flash が主流でしたが、HTML5 の普及とともに CSS3 アニメーションが登場し、宣言的にアニメーションを記述できるようになりました。
JavaScript によるアニメーション制御も、setInterval や setTimeout から requestAnimationFrame へと進化し、よりスムーズな描画が可能になっています。しかし、CSS アニメーションは柔軟性に欠け、JavaScript による独自実装は複雑になりがちという課題がありました。
Web Animations API の誕生
こうした背景から、W3C は 2014 年頃から Web Animations API の標準化を進めてきました。この API は、CSS アニメーションと JavaScript アニメーションの良い部分を統合し、より強力で使いやすいアニメーション制御を実現することを目指しています。
現在では、主要なブラウザでサポートされており、モダンな Web 開発において重要な技術となっているのです。
以下の図は、従来のアニメーション手法と Web Animations API の関係性を示しています。
mermaidflowchart TB
old1["setInterval/setTimeout"] --> waapi["Web Animations API"]
old2["requestAnimationFrame"] --> waapi
css["CSS Animations"] --> waapi
jquery["jQuery.animate()"] -.-> waapi
waapi --> benefit1["パフォーマンス<br/>(CSS並み)"]
waapi --> benefit2["柔軟な制御<br/>(JavaScript)"]
waapi --> benefit3["標準化された<br/>API"]
この図からわかるように、Web Animations API は従来の複数の手法を統合し、それぞれの利点を活かした設計になっています。
主要ブラウザのサポート状況
| # | ブラウザ | サポート開始バージョン | 備考 |
|---|---|---|---|
| 1 | Chrome | 36+ | フル対応 |
| 2 | Firefox | 48+ | フル対応 |
| 3 | Safari | 13.1+ | フル対応 |
| 4 | Edge | 79+ | Chromium 版以降 |
| 5 | Opera | 23+ | フル対応 |
現在では、ほとんどのモダンブラウザで利用できるため、実務での採用も十分に検討できる状況です。
課題
従来のアニメーション実装における問題点
Web アニメーションを実装する際、開発者はいくつかの課題に直面してきました。それぞれの手法には、明確な制限や欠点が存在していたのです。
CSS アニメーションの制約
CSS アニメーションは宣言的で記述しやすい反面、動的な制御が困難です。アニメーションの途中で速度を変更したり、一時停止・再開したりする操作は、JavaScript から CSS クラスを切り替える複雑な実装が必要になります。
また、アニメーションの進行状況を取得することも容易ではありません。これにより、複雑なインタラクションを実装する際に大きな制約となっていました。
JavaScript による独自実装の複雑さ
一方、requestAnimationFrame を使った JavaScript 実装は柔軟性が高いものの、タイミング制御やイージング関数の実装など、低レベルな処理を自分で書く必要があります。
これは開発コストの増加につながり、また実装によってパフォーマンスにばらつきが生じる原因にもなっていました。
以下の図は、従来のアニメーション実装における課題を整理したものです。
mermaidflowchart TB
subgraph css_issues["CSS アニメーションの課題"]
css1["動的制御が困難"]
css2["進行状況の取得が難しい"]
css3["複雑なタイミング制御<br/>に不向き"]
end
subgraph js_issues["JavaScript 実装の課題"]
js1["低レベルな処理の<br/>実装が必要"]
js2["パフォーマンス最適化<br/>が難しい"]
js3["コード量が多く<br/>なりがち"]
end
css_issues --> need["統一的な<br/>API の必要性"]
js_issues --> need
need --> waapi_solution["Web Animations API<br/>による解決"]
この図が示すように、CSS と JavaScript それぞれの課題を解決する統一的な API が求められていたのです。
具体的な実装上の困難
開発現場では、以下のような具体的な問題に悩まされることが多くありました。
| # | 課題 | CSS の場合 | JavaScript の場合 |
|---|---|---|---|
| 1 | アニメーション制御 | クラス操作が必要 | 自前実装が複雑 |
| 2 | 進行状況の取得 | ほぼ不可能 | 計算処理が必要 |
| 3 | 一時停止・再開 | 実装が困難 | 状態管理が複雑 |
| 4 | 複数要素の同期 | タイミング調整困難 | コード量増加 |
| 5 | パフォーマンス | 良好 | 実装次第 |
これらの課題を解決し、開発者がより簡単に高品質なアニメーションを実装できる環境が必要だったのです。
解決策
Web Animations API による統合的アプローチ
Web Animations API は、従来の課題を解決するために設計された強力な API です。CSS アニメーションのパフォーマンスを維持しながら、JavaScript による柔軟な制御を可能にしています。
この API の最大の特徴は、Element.animate() メソッドを使って、わずか数行のコードでアニメーションを実装・制御できる点です。CSS で定義していたアニメーションを、そのまま JavaScript オブジェクトとして記述できるため、学習コストも低く抑えられます。
基本的な API 構造
Web Animations API の中心となるのは、Element.animate() メソッドです。このメソッドは、アニメーション対象の要素に対して呼び出し、キーフレームとオプションを指定することでアニメーションを実行します。
返り値として Animation オブジェクトが返され、このオブジェクトを通じてアニメーションの再生・一時停止・逆再生などの制御が可能になるのです。
以下の図は、Web Animations API の基本的な構造を示しています。
mermaidflowchart LR
element["DOM 要素"] --|animate()|--> animation["Animation オブジェクト"]
keyframes["キーフレーム<br/>(配列)"] --> animate_method["element.animate()"]
optionsNode["オプション<br/>(duration, easing等)"] --> animate_method
animate_method --> animation
animation --> control1["play()"]
animation --> control2["pause()"]
animation --> control3["reverse()"]
animation --> control4["cancel()"]
animation --> stateInfo["currentTime<br/>playState など"]
この図が示すように、API はシンプルで直感的な構造になっており、要素に対してメソッドを呼び出すだけでアニメーションを開始できます。
Web Animations API の主要機能
この API が提供する主要な機能を、以下の表にまとめました。
| # | 機能 | 説明 | メリット |
|---|---|---|---|
| 1 | キーフレーム定義 | CSS 風のオブジェクト記法 | 直感的で理解しやすい |
| 2 | タイミング制御 | duration、delay、iterations 等 | 細かい調整が可能 |
| 3 | イージング | ease、linear、cubic-bezier 等 | 自然な動きを実現 |
| 4 | 再生制御 | play、pause、reverse 等 | 動的な制御が容易 |
| 5 | 状態取得 | playState、currentTime 等 | 進行状況の監視が簡単 |
| 6 | Promise 対応 | finished、ready プロパティ | 非同期処理との連携 |
これらの機能により、従来の課題が包括的に解決されているのです。
アニメーションのライフサイクル
Web Animations API で作成されたアニメーションには、明確なライフサイクルが存在します。このライフサイクルを理解することで、より効果的にアニメーションを制御できるようになりますね。
mermaidstateDiagram-v2
[*] --> idle: アニメーション生成
idle --> pending: play() 呼び出し
pending --> running: 開始遅延後
running --> paused: pause() 呼び出し
paused --> running: play() 呼び出し
running --> finished_state: 完了
finished_state --> running: play() 呼び出し
running --> idle: cancel() 呼び出し
paused --> idle: cancel() 呼び出し
finished_state --> [*]
この状態遷移図により、アニメーションがどのような状態を持ち、どのように遷移するかが理解できます。各状態で適切なメソッドを呼び出すことで、意図した動作を実現できるのです。
具体例
基本的なフェードインアニメーション
まずは、最もシンプルなフェードインアニメーションから始めましょう。要素を徐々に表示させる、基本中の基本となる実装です。
以下のコードは、HTML 要素を取得してフェードインアニメーションを適用します。
html<!-- HTML -->
<div id="fadeTarget" class="box">フェードイン</div>
javascript// 対象要素を取得
const element = document.getElementById('fadeTarget');
次に、animate() メソッドを使ってアニメーションを定義します。第一引数にキーフレーム、第二引数にオプションを指定する形式です。
javascript// フェードインアニメーションを実行
const animation = element.animate(
// キーフレーム:開始状態と終了状態を配列で指定
[
{ opacity: 0 }, // 開始:完全に透明
{ opacity: 1 }, // 終了:完全に不透明
],
// オプション:アニメーションの詳細設定
{
duration: 1000, // 1秒間かけて実行
easing: 'ease-out', // 終わりに向けて減速
fill: 'forwards', // アニメーション終了後も最終状態を維持
}
);
このコードでは、opacity プロパティを 0 から 1 へと変化させることで、フェードイン効果を実現しています。fill: 'forwards' を指定することで、アニメーション終了後も opacity: 1 の状態が維持されます。
スライドインアニメーション
次は、要素を左からスライドさせながらフェードインさせる、より複雑なアニメーションです。複数のプロパティを同時にアニメーションさせることで、よりリッチな表現が可能になります。
javascript// スライド+フェードインアニメーション
const slideAnimation = element.animate(
[
{
transform: 'translateX(-100px)', // 左に100px オフセット
opacity: 0, // 透明
},
{
transform: 'translateX(0)', // 元の位置
opacity: 1, // 不透明
},
],
{
duration: 800, // 0.8秒
easing: 'ease-in-out', // 開始と終了を滑らかに
fill: 'both', // 開始前と終了後の両方で状態を維持
}
);
transform と opacity を組み合わせることで、より動的で魅力的なアニメーションを作成できました。easing: 'ease-in-out' により、開始時と終了時に加減速が加わり、自然な動きになっています。
アニメーションの制御
Web Animations API の真価は、アニメーションを動的に制御できる点にあります。ユーザーの操作に応じて、一時停止や逆再生などを簡単に実装できるのです。
javascript// アニメーションオブジェクトを保持
const controlledAnimation = element.animate(
[
{ transform: 'rotate(0deg)' },
{ transform: 'rotate(360deg)' },
],
{
duration: 2000,
iterations: Infinity, // 無限ループ
}
);
このアニメーションオブジェクトに対して、さまざまな制御メソッドを呼び出すことができます。
javascript// 一時停止
controlledAnimation.pause();
// 再開
controlledAnimation.play();
// 逆再生
controlledAnimation.reverse();
// キャンセル(初期状態に戻す)
controlledAnimation.cancel();
// 再生速度の変更(2倍速)
controlledAnimation.playbackRate = 2;
これらのメソッドを使うことで、ボタンクリックなどのイベントに応じたインタラクティブなアニメーションを実装できます。従来の CSS アニメーションでは困難だった、細かい制御が可能になっているのです。
進行状況の取得と監視
アニメーションの現在の状態や進行状況を取得することも、Web Animations API では簡単です。これにより、他の処理と連携させたり、UI に進捗を表示したりできます。
javascript// 再生状態の取得
console.log(animation.playState);
// 'idle', 'pending', 'running', 'paused', 'finished' のいずれか
// 現在の再生時間(ミリ秒)
console.log(animation.currentTime);
// アニメーション全体の長さ
console.log(animation.effect.getTiming().duration);
さらに、Promise を使ってアニメーションの完了を待つこともできます。
javascript// アニメーション完了を待つ
animation.finished.then(() => {
console.log('アニメーションが完了しました');
// 次のアニメーションを開始するなど
});
// アニメーションの準備完了を待つ
animation.ready.then(() => {
console.log('アニメーションの準備ができました');
// 正確なタイミングで何かを実行
});
これにより、複数のアニメーションを順番に実行したり、アニメーション完了後に特定の処理を行ったりすることが容易になります。
複数要素の連続アニメーション
実際のアプリケーションでは、複数の要素を順番にアニメーションさせたいケースがよくあります。Promise を活用することで、エレガントに実装できるのです。
以下は、リストアイテムを順番にフェードインさせる例です。
javascript// 複数の要素を取得
const items = document.querySelectorAll('.list-item');
// 連続してアニメーションさせる関数
async function animateSequentially() {
for (let i = 0; i < items.length; i++) {
// 各アイテムにアニメーションを適用
const animation = items[i].animate(
[
{ opacity: 0, transform: 'translateY(20px)' },
{ opacity: 1, transform: 'translateY(0)' },
],
{
duration: 400,
easing: 'ease-out',
fill: 'forwards',
}
);
// 完了を待ってから次へ
await animation.finished;
// 少し間を空ける
await new Promise((resolve) =>
setTimeout(resolve, 100)
);
}
}
// 実行
animateSequentially();
この実装により、リストアイテムが順番に現れる滑らかなアニメーションを実現できます。async/await を使うことで、コードの可読性も高く保たれていますね。
キーフレームの詳細な制御
Web Animations API では、2 つのキーフレームだけでなく、より細かいステップを定義することもできます。オフセットを指定することで、アニメーションの途中経過を詳細に制御できるのです。
javascript// 複雑なバウンスアニメーション
const bounceAnimation = element.animate(
[
// 各キーフレームにオフセット(0〜1の値)を指定可能
{ transform: 'translateY(0)', offset: 0 }, // 0%の時点
{ transform: 'translateY(-100px)', offset: 0.4 }, // 40%の時点
{ transform: 'translateY(-50px)', offset: 0.6 }, // 60%の時点
{ transform: 'translateY(-75px)', offset: 0.8 }, // 80%の時点
{ transform: 'translateY(0)', offset: 1 }, // 100%の時点
],
{
duration: 1500,
easing: 'linear',
}
);
この例では、バウンスするような動きを実現するために、5 つのキーフレームを定義しています。offset プロパティで各キーフレームのタイミングを指定することで、細かい動きの調整が可能です。
イージング関数のカスタマイズ
アニメーションの「緩急」を制御するイージング関数も、柔軟にカスタマイズできます。CSS と同じく、cubic-bezier を使った独自のイージング曲線を定義できるのです。
javascript// カスタムイージングを使ったアニメーション
const customAnimation = element.animate(
[{ transform: 'scale(1)' }, { transform: 'scale(1.5)' }],
{
duration: 1000,
// ベジェ曲線でカスタムイージング
easing: 'cubic-bezier(0.68, -0.55, 0.265, 1.55)',
fill: 'forwards',
}
);
この cubic-bezier(0.68, -0.55, 0.265, 1.55) は、オーバーシュート(行き過ぎてから戻る)効果を持つイージング曲線です。こうしたカスタマイズにより、ブランドやデザインに合わせた独自の動きを作り出せます。
実践的なユースケース:モーダルの表示
実際のアプリケーションでよく使われる、モーダルダイアログの表示アニメーションを実装してみましょう。背景のオーバーレイとモーダル本体を、それぞれアニメーションさせます。
javascript// モーダル表示関数
function showModal() {
const overlay = document.getElementById('overlay');
const modal = document.getElementById('modal');
// 要素を表示
overlay.style.display = 'block';
modal.style.display = 'block';
// オーバーレイのフェードイン
overlay.animate([{ opacity: 0 }, { opacity: 1 }], {
duration: 300,
easing: 'ease-out',
fill: 'forwards',
});
// モーダルのスケール+フェードイン
modal.animate(
[
{
transform: 'scale(0.7)',
opacity: 0,
},
{
transform: 'scale(1)',
opacity: 1,
},
],
{
duration: 300,
easing: 'cubic-bezier(0.34, 1.56, 0.64, 1)',
fill: 'forwards',
}
);
}
この実装では、オーバーレイとモーダルを別々にアニメーションさせることで、より洗練された表示効果を実現しています。
モーダルを閉じる際も、同様にアニメーションを適用できます。
javascript// モーダル非表示関数
async function hideModal() {
const overlay = document.getElementById('overlay');
const modal = document.getElementById('modal');
// モーダルのアニメーション
const modalAnim = modal.animate(
[
{
transform: 'scale(1)',
opacity: 1,
},
{
transform: 'scale(0.7)',
opacity: 0,
},
],
{
duration: 200,
easing: 'ease-in',
fill: 'forwards',
}
);
// オーバーレイのアニメーション
const overlayAnim = overlay.animate(
[{ opacity: 1 }, { opacity: 0 }],
{
duration: 200,
easing: 'ease-in',
fill: 'forwards',
}
);
// 両方のアニメーション完了を待つ
await Promise.all([
modalAnim.finished,
overlayAnim.finished,
]);
// アニメーション完了後に要素を非表示
overlay.style.display = 'none';
modal.style.display = 'none';
}
Promise.all() を使うことで、複数のアニメーションが完了するのを効率的に待つことができます。完了後に display: none を設定することで、DOM から完全に隠すことができるのです。
パフォーマンス最適化のポイント
Web Animations API は高パフォーマンスですが、さらに最適化するためのポイントがいくつかあります。特に、アニメーション対象のプロパティ選択が重要です。
以下の表は、アニメーション可能なプロパティとそのパフォーマンスへの影響をまとめたものです。
| # | プロパティ種別 | 例 | パフォーマンス | 理由 |
|---|---|---|---|---|
| 1 | transform | translate, scale, rotate | ★★★ | GPU で処理される |
| 2 | opacity | opacity | ★★★ | GPU で処理される |
| 3 | color | color, background-color | ★★☆ | CPU 処理だが軽量 |
| 4 | layout | width, height, margin | ★☆☆ | レイアウト再計算が発生 |
| 5 | paint | border, box-shadow | ★☆☆ | 再描画が必要 |
可能な限り transform と opacity を使うことで、最高のパフォーマンスを得られます。
javascript// 推奨:transform を使った実装
element.animate(
[
{ transform: 'translateX(0)' },
{ transform: 'translateX(100px)' },
],
{ duration: 500 }
);
// 非推奨:left を使った実装(レイアウト再計算が発生)
element.animate([{ left: '0px' }, { left: '100px' }], {
duration: 500,
});
同じ視覚効果でも、transform を使うことで GPU アクセラレーションが効き、スムーズなアニメーションになります。
まとめ
Web Animations API は、モダンな Web アプリケーションにおいて、滑らかで制御可能なアニメーションを実装するための強力なツールです。CSS アニメーションのパフォーマンスと、JavaScript の柔軟な制御を両立させた、まさに理想的な API といえるでしょう。
本記事では、Web Animations API の基本から実践的な使い方まで解説してきました。Element.animate() メソッドを使った基本的なアニメーションから、Promise を活用した複数要素の制御、実際のアプリケーションで使えるモーダル表示まで、幅広くカバーしています。
重要なポイントをまとめると、以下のようになります。
- シンプルな API:
animate()メソッド一つで直感的にアニメーションを実装できる - 柔軟な制御: play、pause、reverse など、動的な制御が簡単
- Promise 対応: 非同期処理との連携や、アニメーションの順次実行が容易
- 高パフォーマンス: 特に transform と opacity は GPU アクセラレーションが効く
- 標準化: 主要ブラウザでサポートされ、実務でも十分に使える
この API をマスターすることで、ユーザー体験を大きく向上させる、魅力的な UI を構築できるようになります。ぜひ実際のプロジェクトで活用して、滑らかで心地よいアニメーションを実装してみてください。
最初は基本的なフェードインやスライドから始めて、徐々に複雑なアニメーションに挑戦していくことをおすすめします。Web Animations API は学習曲線が緩やかで、段階的にスキルアップできる技術なのです。
関連リンク
articleJavaScript Web Animations API:滑らかに動く UI を設計するための基本と実践
articleJavaScript Service Worker 運用術:オフライン対応・更新・キャッシュ戦略の最適解
articleJavaScript パフォーマンス最適化大全:レイアウトスラッシングを潰す実践テク
articleJavaScript IntersectionObserver レシピ集:無限スクロール/遅延読込を最短実装
articleJavaScript Web Workers 実践入門:重い処理を別スレッドへ逃がす最短手順
articleJavaScript OffscreenCanvas 検証:Canvas/OffscreenCanvas/WebGL の速度比較
articleGitHub Copilot Workspace 速理解:仕様 → タスク分解 →PR までの“自動開発”体験
articleMySQL InnoDB 内部構造入門:Buffer Pool/Undo/Redo を俯瞰
articleMotion(旧 Framer Motion)で学ぶ物理ベースアニメ:バネ定数・減衰・質量の直感入門
articleJavaScript Web Animations API:滑らかに動く UI を設計するための基本と実践
articleGitHub Actions コンテキスト辞典:github/env/runner/secrets の使い分け最速理解
articlehtmx で管理画面 CRUD を 10 倍速に:一覧・検索・編集・バルク操作テンプレ
blogiPhone 17シリーズの発表!全モデルiPhone 16から進化したポイントを見やすく整理
blogGoogleストアから訂正案内!Pixel 10ポイント有効期限「1年」表示は誤りだった
blog【2025年8月】Googleストア「ストアポイント」は1年表記はミス?2年ルールとの整合性を検証
blogGoogleストアの注文キャンセルはなぜ起きる?Pixel 10購入前に知るべき注意点
blogPixcel 10シリーズの発表!全モデル Pixcel 9 から進化したポイントを見やすく整理
blogフロントエンドエンジニアの成長戦略:コーチングで最速スキルアップする方法
review今の自分に満足していますか?『持たざる者の逆襲 まだ何者でもない君へ』溝口勇児
reviewついに語られた業界の裏側!『フジテレビの正体』堀江貴文が描くテレビ局の本当の姿
review愛する勇気を持てば人生が変わる!『幸せになる勇気』岸見一郎・古賀史健のアドラー実践編で真の幸福を手に入れる
review週末を変えれば年収も変わる!『世界の一流は「休日」に何をしているのか』越川慎司の一流週末メソッド
review新しい自分に会いに行こう!『自分の変え方』村岡大樹の認知科学コーチングで人生リセット
review科学革命から AI 時代へ!『サピエンス全史 下巻』ユヴァル・ノア・ハラリが予見する人類の未来