requestAnimationFrameについて

3711 ワード

まず文字通り、アニメーションフレームを要求する(後でrafで代用する).アニメーションといえば、css 3のtransitionやanimation、jsのsettimeoutやsetInterval、jqueryのanimate()がアニメーション化できるなど、いくつかの方法の性能や効率も異なります.今日話したこれもアニメができます.
何だ?
はっきり言ってフレームアニメーションを作るためのもので、アニメーションフレームを要求するというのは、ブラウザに次のスクリーンリフレッシュのときにrafを実行する方法を忘れないように伝えることです.この点に注意してください.スクリーンリフレッシュのたびにrafが実行されます.すなわちrafの動作周波数は、スクリーンリフレッシュ周波数に応じて決定される.
性能はどうですか.
まずsettimeoutについて話します.settimeoutは、実は間隔を設定することで画像の位置を絶えず変更し、アニメーション効果を達成します.しかし、seTimeoutで実装されたアニメーションは、一部のローエンドマシンでカートン、ジッタの現象が発生することがわかります.この現象の発生には2つの原因がある.
1.settimeoutの実行時間は決定されません.Javascriptではsettimeoutタスクが非同期キューに格納され、実際にはブラウザUIスレッドにアニメーションコードを追加して実行を待つ時間を指定しただけで、キューの前に他のタスクがある場合、メインスレッド上のタスクが実行された後にのみ、そのキュー内のタスクが実行を開始する必要があるかどうかをチェックします.従ってsettimeoutの実際の実行時間は、設定された時間よりも遅くなるのが一般的である.2.リフレッシュ頻度は画面解像度と画面サイズの影響を受けるため、異なるデバイスの画面リフレッシュ頻度が異なる場合がありますが、settimeoutは一定の間隔しか設定できません.この時間は必ずしも画面のリフレッシュ時間と同じではありません.どちらの場合もsettimeoutの実行ペースと画面のリフレッシュペースが一致せず、フレームを失う現象を引き起こす.では、なぜ歩調が合わないとフレームを失うのでしょうか.
まず、settimeoutの実行はメモリ内で画像属性を変更するだけであり、この変更は画面が次回リフレッシュされるまで画面に更新されない必要があることを理解しなければならない.両者の歩調が一致しないと、中間のフレームの動作が過去に乗り越えられ、次のフレームの画像が直接更新される可能性がある.画面が16.7 msごとにリフレッシュされ、settimeoutが10 msごとに設定された画像が1 px左に移動すると、次の描画プロセスが発生します.
0 ms目:画面がリフレッシュされず、待機中、settimeoutも実行されず、待機中.第10 ms:画面がリフレッシュされず、待機中、settimeoutが実行を開始し、画像属性left=1 pxを設定する.第16.7 ms:画面がリフレッシュを開始し、画面上の画像が左に1 px移動し、settimeoutが実行されず、待機中である.第20 ms:画面がリフレッシュされず、待機中、settimeoutが実行を開始しleft=2 pxを設定する.第30 ms:画面がリフレッシュされず、待機中、settimeoutが実行を開始しleft=3 pxを設定する.第33.4 ms:画面がリフレッシュを開始し、画面上の画像が左に3 px移動し、settimeoutが実行されず、待機中である.上の描画過程から分かるように、スクリーンはleft=2 pxのフレーム画面を更新しておらず、画像は直接1 pxの位置から3 pxの位置にジャンプし、これがフレームを失う現象であり、この現象はアニメーションカートンを引き起こす.したがって、フレーム損失現象は、スクリーンリフレッシュ周波数とコード実行の非対称性に起因すると言える.
では、スクリーンリフレッシュ周波数とコードが対称に実行されると、フレームを失う現象は発生しませんか??rafの誕生はこの点を解決し、上述したように、rafの実行周波数はスクリーンリフレッシュ周波数によって言えば、画像の変化があればスクリーンをリフレッシュし、スクリーンをリフレッシュすればrafを実行し、フレームを失う現象を解決する.
使用方法
raf()は、次の再描画時のdomのスタイルを変更する役割を果たす関数であるパラメータを受信します.
var i = 0;
function updateDom(){
  let box = document.getElementById('box');
  i+=10;
  box.style.width = 300 + i +'px';
  if(i<500){
      requestAnimationFrame(updateDom)
  }
}
requestAnimationFrame(updateDom)

これによりrafはアニメーションがいつから最適なループ間隔となるかという問題を解決したが,コードが具体的にどの時間に実行されるかは確かに分からず,アニメーションがスクリーンリフレッシュ時に開始されることしか知らない.ただし、mozRequestAnimationFrame()が渡す関数は、次の再描画が発生する実際の時間を示すタイムコード(1970年1月1日から現在までのミリ秒数)のパラメータも受信します.前回の再描画までの時間を知りたければ、mozAnimationStartTimeを問い合わせることができますが、この属性知識Mozillaは実現しました.現在chromeとIEにはこの属性はありません.この値には前回再描画されたタイムコードが含まれており、コールバック関数に入力されたタイムコードからこの時間を減算すると、画面に次のクラスタの変化を再描画するまでにどれだけの時間がかかるかを計算できます.
function draw(timestamp){
  var differ = timestamp - startTime;//differ                 
  startTime = timestamp;// timestamp           
  mozRequestAnimationFrame(draw);
}
var startTime = mozAnimationStartTime;
mozRequestAnimationFrame(draw)

chromeとIE 10+はいずれも接頭辞付きrequestAnimationFrameメソッド実装を与えているが,Mozillaのバージョンとは少し異なる.差異1:コールバック関数にタイムコードを返さない.違い2:chromeは2番目のオプションパラメータを追加しました:間もなく変化するDOM要素です.chromeは、以前に計画された再描画操作をキャンセルするためのフレームアニメーションをキャンセルする方法を提供します.もちろん、新しいAPIとして、互換性の問題は少なくないに違いない.実際の開発では互換性の処理に注意してください.
requestAnimationFrameの利点:1.複数のrafは並列に描画できます.(この点はsettimeoutとsetIntervalが非同期キューに入ることと関係がある.)2.非表示または非表示の要素の要約では、rafは再描画および還流を行わず、CPUおよびGPUおよびメモリ使用量がより少ないことを意味します.
  • ブラウザがアニメーション専用に提供するAPIは、実行時にブラウザがメソッドの呼び出しを自動的に最適化し、ページがアクティブでない場合、アニメーションが一時停止し、CPUのオーバーヘッドを節約します.(この点について、settimeoutとsetIntervalを試してみると、この2つで作った動画は非アクティブな状態でも一時停止していることに気づき、chromeブラウザが最適化したのか、それともchromeだけがそうだったのか分かりません.)

  • 4.関数スロットル:高周波時間(resize,scrollなど)では、1つのリフレッシュ間隔内で複数回の関数実行が発生することを防止するために、rafを使用してリフレッシュ間隔ごとに1回しか実行できないことを保証し、放浪性を保証し、関数実行のオーバーヘッドをよりよく節約することができる.