タイマーは常に JavaScript アニメーションの中核テクノロジーでした。アニメーション ループを作成する際の鍵は、遅延時間の長さを知ることです。ループ間隔は、さまざまなアニメーション効果が滑らかに見えるように十分に短くなければなりませんが、一方で、ループ間隔はブラウザが結果の変更をレンダリングできるように十分に長くなければなりません。
ほとんどのコンピューター モニターのリフレッシュ レートは 60 Hz で、これは 1 秒あたり 60 回の再描画にほぼ相当します。ほとんどのブラウザでは、再描画操作がディスプレイの再描画頻度以下に制限されます。これは、その頻度を超えてもユーザー エクスペリエンスが向上しないためです。したがって、最もスムーズなアニメーションに最適なループ間隔は 1000 ミリ秒/60、つまり 16.6 ミリ秒にほぼ等しくなります。
setTimeout と setInterval の問題は、それらが正確ではないことです。内部操作メカニズムは、時間間隔パラメーターが実際には、実行を待機するためにブラウザー UI スレッド キューにアニメーション コードを追加する時間を指定するだけであると判断します。他のタスクがキューの先頭に追加されている場合、アニメーション コードは前のタスクが完了するまで待ってから実行する必要があります。
requestAnimationFrame は、最適な描画効率を維持するためにシステムの時間間隔を使用します。間隔が短すぎるために過剰な描画が発生したり、オーバーヘッドが増加したりすることはありません。また、間隔が長すぎるためにアニメーションが停止したり、滑らかでなくなったりすることもありません。さまざまな Web ページ アニメーション効果を実現するため、システム リソースを節約し、システム パフォーマンスを向上させ、視覚効果を向上させるための統合された更新メカニズムがあります。
特徴requestAnimationFrame メソッドはコールバックをパラメーターとして受け取り、そのコールバック関数はパラメーター DOMHighResTimeStamp で渡され、現在 requestAnimationFrame() によってソートされているコールバック関数がトリガーされる時間を示します。戻り値はリクエスト ID で、コールバック リスト内の一意の識別子を表します。この値を window.cancelAnimationFrame() に渡すと、コールバック関数をキャンセルできます。
requestID = window.requestAnimationFrame(callback);
この API を使用すると、次回の再レンダリング中に特定のコードを実行して、短期間に大量のリフローがトリガーされるのを回避できます。
たとえば、ページ スクロール イベント (scroll) のコールバック関数は、次の再レンダリングまでコールバック操作を延期するため、この API の使用に非常に適しています。ただし、requestAnimationFrame はコールバック関数を管理しないことに注意してください。つまり、コールバックが実行される前に同じコールバック関数で requestAnimationFrame を複数回呼び出すと、コールバックが同じフレーム内で複数回実行されることになります。最も簡単な方法は、スロットリング関数を使用してこの問題を解決することです。または、requestAnimationFrame のキューに同じコールバック関数を 1 つだけ置く方法を見つけることもできます。
let selectedAnimationFrame = false;document.body.onscroll = () => { if (scheduledAnimationFrame) return; selectedAnimationFrame = true; window.requestAnimationFrame(() => { selectedAnimationFrame = false; // 何かを行います });};
もちろん、最適なアプリケーション シナリオはやはりフレーム アニメーションであり、パフォーマンスを大幅に最適化できます。
面接での質問インターフェースに引っかかることなく数万のデータをレンダリングする方法この質問では、ページをブロックせずにデータをレンダリングする方法を検討します。つまり、一度に数万のアイテムをレンダリングすることはできませんが、requestAnimationFrame を通じて 16 ミリ秒ごとに DOM の一部をレンダリングする必要があります。
<!DOCTYPE html><html lang=ja><head> <meta charset=UTF-8> <meta name=viewport content=width=device-width、initial-scale=1.0> <meta http-equiv=X-UA -互換コンテンツ=ie=edge> <title>ドキュメント</title></head><body> <ul>コントロール</ul> <script> setTimeout(() => { // 100,000 個のデータを挿入します const total = 100000 // パフォーマンスが良くないと感じる場合は、一度に const を減らします = 20 // データをレンダリングするのに何回かかりますか? const blockCount = total / Once let countOfRender = 0 let ul = document.querySelector(ul); function add() { // パフォーマンスを最適化します。挿入によりバックフローが発生しません const flagment = document.createDocumentFragment() for (let i = 0; i <一度; i++) { const li = document.createElement(li); li.innerText = Math.floor(Math.random() * total); ul.appendChild(fragment); 1; ループ(); } 関数ループ() { if (countOfRender < ループカウント) { window.requestAnimationFrame(add);ループ() }, 0);互換性
一部の古いブラウザーはこの API をサポートしていません。この API を使用するには、このメソッドをカスタマイズしてウィンドウの下にマウントします。
(function() { var lastTime = 0; varベンダー = ['webkit', 'moz']; for(var x = 0; x <venders.length && !window.requestAnimationFrame; ++x) { window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame']; window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'] } if (!window.requestAnimationFrame) window.requestAnimationFrame = function(callback) { var currTime = new Date().getTime(); 0, 16 - (currTime - lastTime)); var id = window.setTimeout(function() { callback(currTime +) timeToCall); }、timeToCall); lastTime = currTime + timeToCall; if (!window.cancelAnimationFrame) {clearTimeout(id);
以上がこの記事の全内容です。皆様の学習のお役に立てれば幸いです。また、VeVb Wulin Network をご支援いただければ幸いです。