ウェブアニメーションのフレームレートFPSを計算する方法

ウェブアニメーションのフレームレートFPSを計算する方法

スムーズなアニメーションの基準

まず、いくつかの概念を明確にしましょう。 FPS は 1 秒あたりの画面更新回数を意味します。私たちが普段目にする連続画像は、一連の静止画像で構成されています。各画像はフレームと呼ばれます。FPS は、「フレーム」が変化する速度を表す物理量です。

理論的には、FPS が高いほど、アニメーションはスムーズになります。現在、ほとんどのデバイスの画面リフレッシュ レートは 1 秒あたり 60 回であるため、一般的に、アニメーション効果は FPS が 60 フレーム/秒、つまり各フレームに 16.67 ミリ秒かかるときに最適になります。

もちろん、FPSゲームをよくプレイする友人は、PUBG/CSGOな​​どのFPSゲームでは144Hzのリフレッシュレートのモニターの使用が推奨されていることを知っているはずです。144Hzモニターとは、具体的には1秒あたり144Hzのリフレッシュレートのモニターを指します。通常のモニターの60秒のリフレッシュレートと比較すると、画像の表示がよりスムーズになります。したがって、144Hz モニターは、視野角が高速移動を維持することが多い一人称シューティング ゲームに適しています。

ただし、これはディスプレイが提供する高リフレッシュ レート機能にすぎません。Web アニメーションの場合、サポートされるかどうかはブラウザーによって異なり、ほとんどのブラウザーのリフレッシュ レートは 1 秒あたり 60 回です。

直感的な感覚、さまざまなフレームレートの体験:

  • フレームレートが 50 ~ 60 FPS のアニメーションは非常にスムーズで快適です。
  • フレーム レートが 30 ~ 50 FPS のアニメーションの場合、感度レベルが異なるため、快適さのレベルは人によって異なります。
  • フレームレートが 30 FPS 未満のアニメーションでは、明らかな遅延と不快感を感じます。
  • フレームレートの変動が大きいアニメーションも、遅延を感じさせる原因になります。

さて、ページアニメーションの現在の FPS 値を正確に取得するにはどうすればよいでしょうか?

方法1: Chromeデベロッパーツールを使用する

Chrome は開発者向けに強力な機能を提供します。開発者ツールでは、次のように FPS メーター オプションを選択できます。

このボタンを使用すると、ページのフレーム レートのリアルタイム監視とページの GPU 使用率をオンにすることができます。

欠点:

  • 一度に1ページまたは数ページしか観察できず、手動でリアルタイム観察する必要がある。
  • データは主観的なものに過ぎず、継続的に報告または収集される非常に正確なデータは存在しません。

したがって、より賢明なアプローチが必要です。

方法 2: フレームタイミング API を使用する

次の方法を紹介する前に、基本的な知識を広めていきましょう。

Blinkカーネルの初期アーキテクチャ

Chrome ブラウザ カーネルの Blink レンダリング ページを例に挙げます。初期の Chrome ブラウザでは、各ページ タブは、メイン スレッドと合成スレッドを含む独立したレンダラー プロセスに対応しています。初期の Chrome カーネル アーキテクチャ:

その中で、メインスレッドは主に以下の処理を担当します。

  • Javascriptの計算と実行
  • CSSスタイルの計算
  • レイアウト計算
  • ページ要素をビットマップに描画する(ペイント)、つまりラスタライズする(ラスター)
  • ビットマップを合成スレッドに渡す

構成スレッドは主に次のことを行います。

  • ビットマップ(GraphicsLayerレイヤー)をテクスチャとしてGPUにアップロードする
  • ページの表示されている部分とすぐに表示される部分を計算する(スクロール)
  • CSSアニメーション
  • GPUにビットマップを画面に描画するように指示する

よし、霧さん、これは何ですか?実際、これら 2 つのスレッドを理解した後の次の概念は、CSS アニメーションと JS アニメーション (もちろん、どちらも Web アニメーションです) の微妙な違いを明確にすることです。

JSアニメーションとCSSアニメーションの微妙な違い

JS アニメーションの場合、実行されるフレーム レートは、メイン スレッドと合成スレッドの合計で消費される時間になります。スムーズなアニメーションを実現するには、各フレームの所要時間が 16.67 ミリ秒未満になるようにします。

CSSアニメーションについては、その処理はメインスレッドの影響を受けないため、合成スレッドの消費時間を取得することが期待されます。合成スレッドの描画頻度は、スクロールとCSSアニメーションの処理も反映します。

上記から導き出される主な結論は次のとおりです。メインスレッドと合成スレッドの各フレームにかかる時間がわかれば、対応する Web アニメーションのフレーム レートを大まかに把握できます。では、上記のフレームタイミング API はこの時点を取得するのに役立ちますか?

フレームタイミング API とは何ですか?

Frame Timing API は、Web Performance Timing API 標準のメンバーです。

Web パフォーマンス タイミング API は、開発者が Web サイトのさまざまな側面のパフォーマンスを正確に分析および制御し、Web サイトのパフォーマンスを向上させるために W3C によって開始されたパフォーマンス API 標準のセットです。

次のように、さまざまな機能を実行するための多くのサブクラス API が含まれています (パフォーマンス API を使用して Web フロントエンドのパフォーマンスを迅速に分析するから抜粋。もちろん、オリジナルの英語の紹介文「Web Performance Timing API」も読むことができます)。

どうやって使うの?ナビゲーション タイミング、パフォーマンス タイムライン、リソース タイミングを例にとると、互換性のあるブラウザーでは、これらは window.performance にマウントされた読み取り専用プロパティとして公開されます。

デバッガー コンソールに window.performance を出力し、タイミング プロパティを確認します。

このオブジェクト内の一連の変数は何を表しているのでしょうか? これらは、ページの読み込みプロセス全体におけるすべての重要な時点を表しています。次の図を詳しく見てみましょう。

この図と上記の window.performance.timing を使用すると、ページの各重要なノードで消費された時間を簡単にカウントできます。これが Web Performance Timing API の威力です。興味があれば、詳細を調べてページ統計に使用することができます。

フレームタイミング API の概要

さて、ようやく本題に戻りましょう。Web Performance Timing API の Frame Timing API を使用すると、各フレームのメイン スレッドと合成スレッドの時間を簡単に取得できます。または、各フレームにかかる時間を直接取得する方が簡単です。

レンダリング メイン スレッドと合成スレッドのレコードを取得します。各レコードに含まれる情報は、コードに示されているように、基本的に次のようになります (「開発者からのフィードバックが必要: フレーム タイミング API」を参照)。

var rendererEvents = window.performance.getEntriesByType("レンダラー");
var 複合スレッドイベント = window.performance.getEntriesByType("複合");

または:

var observer = new PerformanceObserver(function(list) {
    var perfEntries = list.getEntries();
    (var i = 0; i < perfEntries.length; i++) {
        console.log("フレーム: ", perfEntries[i]);
    }
});
 
// フレームタイミングをサブスクライブする
オブザーバー.observe({entryTypes: ['frame']});

各レコードには次の基本情報が含まれています。

{
  ソースフレーム番号: 120,
  開始時間: 1342.549374253
  CPU時間: 6.454313323
}

各レコードには、一意のフレーム番号、フレーム開始時刻、および cpuTime が含まれます。各レコードの startTime を計算することで、2 つのフレーム間の間隔を計算し、アニメーションのフレーム レートが 60 FPS に達するかどうかを判断できます。

しかし! Web Performance Timing API の全体的な互換性を見てみましょう。

Frame Timing API は良いのですが、現時点では互換性があまり良くありません。では、どの程度悪いのでしょうか?まだブラウザのサポートはなく、実験段階であり、将来志向のプログラミングです。私をからかってるの?こんなに長く話しても全然無駄だ…

方法3: requestAnimationFrame APIを使用する

Frame Timing API の説明に多くの時間を費やしましたが、最終的には互換性の問題によりまったく使用できなくなりました。しかし、これはこのような長い説明が役に立たないという意味ではありません。上記の紹介から、各フレームで固定の時点を取得できれば、その 2 つを減算することで 1 つのフレームで消費される時間を概算できることがわかっています。

そこで、別のアプローチを試してみましょう。今回は互換性の良いrequestAnimationFrame APIを使用します。

// 構文 window.requestAnimationFrame(callback);

requestAnimationFrame については、誰もがよく知っているはずです。このメソッドは、アニメーションを実行することをブラウザに伝え、次の再描画の前に、指定された関数を呼び出してアニメーションを更新するようにブラウザに要求します。

画面を更新する準備ができたら、このメソッドを適用します。これには、次のブラウザの再描画の前にアニメーション関数を実行することが必要になります。コールバックの回数は通常 1 秒あたり 60 回で、ほとんどのブラウザは通常 W3C が推奨するリフレッシュ レートと一致します。

requestAnimationFrame を使用して FPS を計算する原理

原則として、通常、requestAnimationFrame メソッドは 1 秒間に 60 回実行され、フレームがドロップされることはありません。アニメーションが時間 A に始まり、時間 B に終了し、x ミリ秒かかるとします。 requestAnimationFrame は合計で n 回実行されるため、このアニメーションのフレーム レートはおおよそ n / (B - A) になります。

コア コードは次のとおりです。これにより、1 秒あたりのページ フレーム レートを概算で計算できます。さらに、各アニメーションのフレーム レートを計算するために使用される rAF の実行回数を記録する allFrameCount も記録します。

var rAF = 関数(){
    戻る (
        ウィンドウのアニメーションフレームをリクエストします。
        window.webkitRequestAnimationFrame ||
        関数(コールバック){
            window.setTimeout(コールバック、1000 / 60);
        }
    );
}();
  
var フレーム = 0;
var allFrameCount = 0;
var lastTime = Date.now();
var lastFameTime = Date.now();
  
var loop = 関数() {
    var now = Date.now();
    var fs = (現在 - lastFameTime);
    var fps = Math.round(1000 / fs);
  
    lastFameTime = 現在;
    // 0 に設定しないでください。アニメーションの開始時と終了時のこの値の差を記録して FPS を計算します。
    すべてのフレーム数++;
    フレーム++;
  
    if (現在 > 1000 + 前回の時刻) {
        var fps = Math.round((frame * 1000) / (now - lastTime));
        console.log(`${new Date()} 1秒以内のFPS:`, fps);
        フレーム = 0;
        前回の時刻 = 現在;
    };
  
    rAF(ループ);
}
 
ループ();

テストのためにアニメーションが継続的に実行されているページを見つけると、コードが次のように実行されることがわかります。

ここでは、以前作成したページを使用してテストしました。Chromeを使用して、同時にページのFPSメーターを呼び出し、両方のリアルタイムFPS値を比較しました。基本的に一致しています。

テストページ、太陽系。上記のコードをこのページのコンソールに貼り付けて、データをテストできます。

右上隅のフレーム レートを比較すると、フレーム レートは基本的に同じです。ほとんどの場合、この方法は Web アニメーションのフレーム レートを適切に推定します。

特定のアニメーション プロセスのフレーム レートをカウントする必要がある場合は、アニメーションの開始時と終了時の allFrameCount の値を記録し、それを途中で消費された時間で割って、特定のアニメーション プロセスの FPS 値を取得するだけです。

この方法で計算された結果と実際のフレーム レートの間には、明らかに食い違いがあることに注意する必要があります。これは、前述のように、メイン スレッドと合成スレッドによって消費された時間を 1 フレームと見なすのではなく、JavaScript の 2 つのメイン スレッド実行間の時間間隔を 1 フレームと見なすためです。しかし、現段階では、それは受け入れられる方法です。

上記は、WebアニメーションのFPSを計算する方法の詳細です。WebアニメーションのFPSの計算の詳細については、123WORDPRESS.COMの他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • python-opencvを使用してビデオを読み取り、ビデオフレームの合計数とFPSを計算します。
  • Unity3DはOnGUIに基づいてFPSをリアルタイムで表示します
  • Unity OnGUIはゲームのFPSをリアルタイムで表示します
  • Pythonはビデオを読み取り、処理し、フレームレートfpsをリアルタイムで計算します。
  • Android で 1 秒あたりのフレーム数 (FPS) を測定する方法
  • Vueはカルーセルのフレームレート再生を実装します

<<:  Mysql の一般的なベンチマーク コマンドの概要

>>:  LinuxでHomebrewを使用する正しい方法

推薦する

Element PlusはAffixを実装します

目次1. コンポーネントの紹介2. ソースコード分析2.1 テンプレート2.2 スクリプト2.3 実...

CentOS7 は rpm を使用して MySQL 5.7 をインストールするチュートリアル図

1. 4つのrpmパッケージをダウンロードする mysql-コミュニティクライアント-5.7.26-...

MySQL で複数のテーブルにビューを作成する方法

MySQLでは、2つ以上のベーステーブルにビューを作成します。学生テーブルとstu_infoテーブル...

Centos7 Zabbix3.4 メールアラーム設定(メール内容がxx.bin添付ファイルになる問題の解決)

目次1. 監視Linuxホストを追加する2. メールボックスを設定する1. 監視Linuxホストを追...

JavaScript PromiseとAsync/Awaitの詳細な説明

目次概要4つの例例1: 誕生日で説明する約束の基本例2: 数字当てゲーム例3: Web APIから国...

MySQLの分離レベルとロックメカニズムの詳細な説明

目次簡単な説明: 1. 取引の4つの特徴2. 複数の同時トランザクションによって発生する問題3. ト...

HTML の blockquote タグの使用と美化

ブロック引用の定義と使用法<blockquote> タグは引用ブロックを定義します。 &...

Vue3 における provide と inject の使用法と原則

序文:親コンポーネントと子コンポーネント間でデータを渡す場合、通常は props と emittin...

Zabbix 5.0 ディスク自動検出と読み取り/書き込み監視の問題を分析する

ディスクを自動的に検出する構成キーの値注: このキー値は Linux プラットフォームでのみサポート...

Docker マルチステージビルドを使用してイメージサイズを縮小する方法

この記事では、Docker のマルチステージ ビルド機能を使用してイメージ サイズを大幅に削減する方...

Linux で特定のユーザーにフォルダーのすべてのコンテンツを許可するにはどうすればよいですか?

【問題分析】 chown コマンドを使用できます。ここで ch は change (変更) を表し...

Vue の get リクエストと post リクエストの違いのまとめ

このチュートリアルの動作環境: Windows 7 システム、vue 2.9.6 バージョン、DEL...

MySQL全文インデックスの原理と欠点

MySQL フルテキスト インデックスは、特定のテーブルの特定の列に表示されるすべての単語のリストを...

Linuxでユーザーが所属するグループを変更する方法

Linuxでユーザーが所属するグループを変更する1. ユーザーのグループを設定する usermod ...

Vueのコンポーネントのprops属性について詳しく説明します

目次質問1: 小道具は具体的にどのように使用されますか?原理は何ですか?下を見る質問 2: 年齢に ...