記事の前半では実例を交えながらrequestAnimationFrameの仕組みと使い方をご説明します。
また、記事の後半ではrequestAnimationFrameを使った繰り返し処理、setTimeout
、setInterval
のように時間指定を行って使用する方法もご説明します。
requestAnimationFrameとは
Javascriptでアニメーションを行う時にrequestAnimationFrameを使うとパフォーマンスの低下を防ぐことができます。
簡単にいうとrequestAnimationFrameは渡した関数をブラウザの表示を邪魔しないタイミングで処理されるようにする関数です。
基本文法
1 2 3 4 | function updateScreen(time) { // ここに処理を記述 } requestAnimationFrame(updateScreen); |
引数に実行したい関数を渡すだけでその関数が、ブラウザにとって最適なタイミングで処理されるようになります。言葉ではなかなか伝わりづらいので、requestAnimationFrameのメリットがわかる例を2つ用意しました。
requestAnimationFrameを使うメリット
メリット1. 関数実行タイミングの最適化
この使い方がrequestAnimationFrameの一般的な用途です。従来よく使われるsetTimeout
、setInterval
などの時間指定の関数はブラウザのフレーム(画面)を更新するタイミングでも関係なく実行されます。その結果、フレーム更新とJavascriptの実行が重なり、フレームレートの低下をもたらします。
フレームの更新を邪魔してしまう例
*アニメーションやスクロールをスムーズに表示するためには、画面のフレームレート(更新頻度)を60fps(16msに一回)に保つことが重要です。
処理タイミングを最適化した例
一方、requestAnimationFrameを利用した場合はフレーム更新の処理直後に引数に渡した処理が実行されます。そのためフレームの更新を邪魔することがなく、フレームレイトを最適に保つことができます。
メリット2. 関数の分割実行
Javascriptの処理が長すぎる場合には、requestAnimationFrameが利用できるケースがあります。
Javascriptの処理が長すぎて処理が更新できない
下図のような場合、Javascriptの処理がおもすぎるため、最適なフレームレートが保てません。
Javascriptの処理を分割して1フレームの処理量を削減
長過ぎる処理の一部をrequestAnimationFrameで処理を分割して、最適なフレームレートを保つ事ができます。
1 2 3 4 5 6 7 8 9 | // 処理を分割 function process1(time) { // 処理1を記載 } function process2(time) { // 処理2を記載 } // 処理2をフレーム更新後に実行 requestAnimationFrame(process2); |
requestAnimationFrameを使ってみよう
フレームごとに繰り返し実行する場合
使い方によってsetIntervalのような処理を実装できます。(この繰り返し処理はブラウザのフレーム更新ごとに行われます。)
また、戻り値をhandlerに保存しておくことで、後にキャンセルをすることが可能となります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | let loopFactry = function(func){ let handler = {}; let loop = function(){ func(); // 次のフレーム時の処理の実行を予約 handler.id = requestAnimationFrame(loop); } // 初回呼び出し handler.id = requestAnimationFrame(loop); return handler; } // 処理を実行 let interval = loopFactry(someloopfunc); // ループをキャンセル cancelAnimationFrame(interval.id); |
requestAnimationFrameのキャンセル処理のデモ
このデモではrequestAnimationFrameで数字をカウントアップして、画面上のどこかをクリックすると処理が停止するように作成されています。
See the Pen
Countup w/ requestAnimationFrame interval Demo by Masahiro Tonomura (@M-Tonomura)
on CodePen.
setTimeout, setIntervalのように時間を指定して実行する
先程の例では時間指定はできませんでしたが、時間を考慮した実装にすることによってrequestAnimationFrame
をsetTimeout
, setInterval
の様に時間指定で実行することもできます。
こちらは@joyrexusさんがコード公開しているので、興味のある方はそちらをご確認ください。
Githubを開くブラウザ対応状況
基本的にメジャーなブラウザでは使用可能です。IEは10以上で使用可能です。
まとめ
setTimeout, setIntervalはブラウザの状況を考えず時間が来たら実行されるため、ブラウザのレンダリングを邪魔してしまうことがあります。
なるべく、requestAnimationFrameを使用して、ブラウザに優しい実装を行いましょう。