JavaScriptのsetTimeoutやsetIntervalをrequestAnimationFrameで置き換える 結城永人 - 2021年4月19日 (月) JavaScriptで関数などを遅らせて実行する時間差の処理に使えるsetTimeout()メソッドと間隔を空けて繰り返せるsetInterval()メソッドには共通するパフォーマンスの問題があって避けるためにはどちらもrequestAnimationFrame()メソッドで置き換えることができる。 目次requestAnimationFrameはジャンクを防ぐrequestAnimationFrameはイベントループに強いアニメーションの始動と時間通りの実行に向くrequestAnimationFrameに時間を設定して使う二秒後に実行して即座に停止するサンプル一秒間隔で実行して十秒で停止するサンプル requestAnimationFrameはジャンクを防ぐ アニメーションの処理に利点があってサイトの表示を良好に保ち易くするのがrequestAnimationFrame()メソッドの大きな特徴だ。 フレームワークまたはサンプルでは、アニメーションのような視覚変化を実現するために setTimeout または setInterval を使用する場合がありますが、これの問題はコールバックがフレームの任意の位置で(おそらくフレームの最後で)実行されることです。そのため、1 つのフレームが見落とされ、ジャンクを発生させることが頻繁にあります。 JavaScript 実行の最適化|Web Fundamentals|Google Developers 現行のブラウザは一秒間に六十回のフレームの更新で描画するけど、アニメーションに関するプログラムはそれとタイミングを合わせるように連動して実行されないとフレーム飛ばしなどのジャンクという画面が乱れるような場合が出て来してしまうかも知れない。 取り分けレイアウトの変更はサイトで広く(最上要素から最下要素まで)影響する可能性があるらしく、例えばコンテンツの挿入などは特に注意しなくてはならないとされる。 JavaScriptのsetTimeout()メソッドや間隔を空けるsetInterval()メソッドも同様に画面のフレームの切り替えには構わず、設定された時間になるとコールバックのプログラムを実行する。 requestAnimationFrame()メソッドを使うと画面のフレームの切り替えに合わせた処理が可能だからアニメーションのサイトのスムーズな閲覧に結び付く。 requestAnimationFrameはイベントループに強い もう一つsetTimeoutやsetIntervalにはイベントループに関して設定した時間通りに必ずしも動作しないという問題もある。 setTimeoutを呼び出すと、2番目の引数として渡された時間が経過した後、メッセージがキューに追加されます。キューに他のメッセージがない場合、メッセージはすぐに処理されます。しかしながら、メッセージがある場合、setTimeoutメッセージは他のメッセージを処理するために待機する必要があります。そのため第二引数は、保証時間ではなく、最小の時間を示しています。 並行モデルとイベントループ|MDN|Mozilla もしも他の処理が先にあれば設定した時間よりも遅れる可能性が出て来るから注意しなくてはならないだろう。 イベントループの他にもブラウザの状況によって遅延が指定値より長い理由が幾つか挙げられるようだ。 requestAnimationFrameだと何よりも画面のフレームの更新に合わせて実行されるので、setTimeoutやsetIntervalと比べてイベントループにもっと強いと考えられる。 アニメーションの始動と時間通りの実行に向く setTimeoutやsetIntervalにはパフォーマンスを低下させ得る二つの問題が含まれているけれどもこれらを一挙に解決し得るのがrequestAnimationFrameによる置き換えなんだ。 requestAnimationFrame()メソッドを使うとサイトのアニメーションの開始をブラウザのフレームの更新に合わせることができる。 このメソッドは、いつでも画面上でアニメーションの更新準備が整った時に呼び出してください。これにより、ブラウザの次の再描画が実行される前にアニメーション関数が呼び出されることを要求します。このコールバックの回数は、たいてい毎秒 60 回ですが、一般的に多くのブラウザーでは W3C の勧告に従って、ディスプレイのリフレッシュレートに合わせて行われます。ただし、コールバックの確率は、バックグラウンドのタブや隠れた <iframe> では、パフォーマンス向上やバッテリー消費を減らすために低くなるでしょう。 Window.requestAnimationFrame()|MDN|Mozilla パフォーマンスの利点としてサイトを閲覧する間に画面が乱れ難いだけではなくて閉じてタブに置いておく間にも描画するフレームを減らすなどの動作の縮小によるデバイスの節電効果もあるらしい。 requestAnimationFrame()メソッドは時間に関してはそれ自体に組み込まれているわけではない。一秒間に六十回のフレーム更新に合わせるだけなので、そのままでは望んだ時間から速くも遅くも動作することになる。なのでsetTimeout()メソッドやsetInterval()メソッドの代わりに時間を設定して使うには幾らか加工しなくてはならない。 幸い、きっかり合わせることが可能で、すると少なくとも気がかりなイベントループによる遅れも免れるから使わない手はないと喜ぶんだ。 requestAnimationFrameに時間を設定して使う サイトでの経過時間をDateコンストラクターからgetTime()メソッドで取得してrequestAnimationFrame()メソッドのフレームに対する動作を条件付ける。 二秒後に実行して即座に停止するサンプル 二秒後に出現:🐼 スタート リセット JavaScript let cancel; function use() { const start = new Date().getTime(); function raf() { const progress = new Date().getTime() - start; if (progress >= 2000) { document.querySelector("span.panda").style.visibility = "visible"; return; } cancel = requestAnimationFrame(raf); } requestAnimationFrame(raf); } ※帯文字は遅らせて実行したい処理の書き込み。 二つの関数で構成されていてrequestAnimationFrameを使うものとそれを時間通りに実行させるための開始時間を取得するものに分かれる。サンプルでは前者のrafが後者のuseの中に入っている。useで得た開始時間をrafの進行時間から差し引いてフレームに合わせた実行時間を算出して条件分岐から所定の遅らせたいプログラムの実行に持って行く。 requestAnimationFrameの基本的な用法だと次のフレームに合わせて実行されるけれども時間を設定する場合は次の次のフレームから実行しなくてはならない。それまで待ちながら反復して使用するためにコールバックの中にも置いて再帰的に実行するようにプログラムする。サンプルでは一番下のrequestAnimationFrame(raf)で発火して初回の実行に入り、反復する二回目の実行からはraf()の内側に記載した初回と同じものによって設定した時間まで繰り返して発火し続けることになる。 requestAnimationFrameは一秒間に六十回のフレームを検出するからブラウザによって挙動は異なるようだけれども最短で0.016秒程度の間隔を持つ。だから二回目以降のフレームは最速でも0.032秒程度以降を想定することになり、非常に短いから実用上は殆ど気にする必要はないかも知れないけど、とにかく時間を設定するときも念頭に置いておくと良いと思う。 動作には僅かでもフレームの更新の間隔があって時間に合わせられるといっても完全に時間通りに実行するプログラムではないわけで、かりに検出される二回目のフレームの0.032秒程度以降を想定するのでなければrequestAnimationFrameを反復して使用する意味はないし、場合によってプログラムのバグの原因ともなり兼ねない。 Ifの条件文の数字が遅らせる時間になる。サンプルはミリ秒の単位で設定する。requestAnimationFrameはフレームの更新に合わせて関数を実行するので、実際は設定した時間ではなくて僅かに遅れた直後のフレームから処理を行うことになる。 一秒間隔で実行して十秒で停止するサンプル 一秒間隔で五回点滅:🐬 スタート リセット JavaScript let cancel; function use() { const start = new Date().getTime(); let i = 1; function raf() { const progress = new Date().getTime() - start; if (progress >= 1000 * i) { i++; document.querySelector("span.dolphin").style.visibility = "hidden"; } else if (progress >= 10000) { document.querySelector("span.dolphin").style.visibility = "visible"; return; } else if (i % 2 !== 0) { document.querySelector("span.dolphin").style.visibility = "visible"; } cancel = requestAnimationFrame(raf); } requestAnimationFrame(raf); } ※帯文字は間隔を空けて実行したい処理の書き込み。 setTimeout()メソッドの遅延処理とsetInterval()メソッドの反復処理で条件付けに関してプログラムが幾らか異なる。前者は時間を取得する幾つかの変数と一つの条件文を追加して可能だけれども後者は間隔を空けて繰り返すための回数を捉える変数が追加される。サンプルのiで、三ヵ所に記載して、何回、間隔を空ける条件文を通過したかで次の間隔を算出している。そして最初の条件文の数字が間隔で、二番目の数字が限界の時間になる。限界の数字の条件文を抜くと一定の間隔で止まらずに繰り返し続けることになる。 どちらのプログラムでも一定の時間が来ると終了するように条件分岐の実行文に遅らせる処理と共にreturnも記載して抜け出すようにしてある。 requestAnimationFrameを止めるためのcancelAnimationFrameメソッドには当該のrequestAnimationFrame()メソッドの返値が必要で、変数のcancelを用意して二回目以降の発火と同時に格納している。スイッチなどに使って止めることができる。または止めないか条件文で抜ける以外に不要ならばrequestAnimationFrameの返値は取得しなくても構わない。 参考サイトウェブアプリのパフォーマンスの問題を特定して修正するWindow.requestAnimationFrame() - 60fpsの間隔で繰り返し処理を実行するImplementing setTimeout using requestAnimationFrame コメント 新しい投稿 前の投稿
細川慎二のどうにも泣けて来てしまうストリートライヴのアルトサックス サックス奏者の 細川慎二 のYouTubeチャンネルの Sax in the Night City で出ているサックスのストリートライヴの動画が美しい音色と相俟った街角の雰囲気の良さで心底と泣けて来るほどの感動を催させる。 細川慎二のアルトサックスの美しい音色が響き渡る街角の...
宜保愛子は本物の霊能力者だと考えられる三つの真実 昭和から平成にかけてテレビや雑誌で何度も大きく取り上げられて物凄く活躍した霊能力者の 宜保愛子 がいた。何気なく昔のテレビ番組を観ていたら霊視は嘘だったと思えない内容で、本当にびっくりした。昔、そんなに引き付けられて観ていたわけではないし、改めて霊能力が本当かどうかを確かめようと...
平田監督の白井球審の誤審への抗議はパワハラへの強力な対処法に他ならない 日本プロ野球で 佐々木朗希が完全試合を実現して 次の試合も八回まで無安打と無失点の状況で、次の試合はどうかと注目した4月24日の対オリックスバファローズ戦は初回の先頭打者の初球にヒットを打たれて五回に二失点を喫して連続の無安打と無失点が両方とも途絶えてしまった。 しかし予想外...
アドセンスのGDPRに日本でも対応しなくてはならない場合がある アドセンスの個人情報のCookieなどの使用に関してサイトの訪問者に同意を得なくてはならない法律としてEU(European Union/欧州連合)の GDPR (General Data Protection Regulation/EU一般データ保護規則)がある。外国の個人情報...
伊良部秀輝が自殺した原因はミッドライフクライシスによる鬱と飲酒だと考える プロ野球選手の 伊良部秀輝 が自殺したと知ってショックを受けたことがあった。もう十年以上前になる。2011年の夏、享年四十二と早過ぎたのに加えて大好きな投手の一人だったので、とても残念に感じた。 目次 伊良部秀輝が大好きだった記憶 負けても自分のスタイルを貫き通した 野球への...
日本人がジャニーズ事務所で行われた性加害よりも恐れていること イギリスの公共放送のBBC(British Broadcasting Corporation/英国放送協会)が日本のジャニーズ事務所の創業者の ジャニー喜多川 の性加害について取り上げたドキュメンタリーの J-POPの捕食者:秘められたスキャンダル に衝撃を受けた。 目次 ジ...
沖雅也の涅槃への自殺と双極性障害 かつて俳優の 沖雅也 の自殺が伝えられたとき、遺書の言葉とされた「おやじ、涅槃でまっている」と共に何なのかと疑問を感じたのを良く覚えている。聞き慣れない「涅槃」という言葉が入っても何十年も過ぎた今振り返っても自殺者の遺書として本当に珍しい表現だったと改めて驚く。 沖雅也が書い...
玉置浩二のメロディーは涙腺緩んで総毛立つ名曲中の名曲だ 玉置浩二 のYouTubeの公式チャンネルで、最も気に入りの メロディー のライブ版が追加されていた。曲自体をちゃんと聴いたのは約二十五年振りかも知れないけど、しかし初めての内容から以前にも況して大変な感動を覚えることになった。 玉置浩二 『メロディー』Live at Tok...
Imgurで画像URLと埋め込みコードを取得する方法 Imgur は自分でアップロードした画像については画像URL/直リンクを取得して他のサイトにHTMLのimgタグで表示させられる。 そして自分と他の人たちも含めて画像の埋め込みコードを取得して他のサイトのHTMLに、そのまま、記載して表示させられもする。 目次 Img...
Googleの誕生祝いでプロフィールアイコンに風船と紙吹雪が飛んで来た サイトを見ていたら妙な感じがするので、良く見てみるとGoogleサービスで、ログインして右上のプロフィールアイコンが出ているときに風船と紙吹雪が飛んで来ていることに気付いた。 Googleから久し振りに受け取った誕生祝い サマリー|Search Console| Goog...
コメント