ホームページ  >  記事  >  ウェブフロントエンド  >  requestAnimationFrame関数の緩和でブラウザアニメーションの実装が改善_基礎知識

requestAnimationFrame関数の緩和でブラウザアニメーションの実装が改善_基礎知識

WBOY
WBOYオリジナル
2016-05-16 17:47:22999ブラウズ

イージング関数の書き方にはrequestAnimationFrame関数を使います 以前習ったことはあるのですが、いつもよく理解できていない気がするので、勉強のために外国人の方が書いた記事を翻訳してみました。共有すること。

requestAnimationFrameとは何ですか?
以前、アニメーションを作成するときは、ミリ秒ごとに何らかの変更を加えるタイマーが必要でした。ここで良いニュースがあります。ブラウザのメーカーは、アニメーション専用のメソッド、つまり requestAnimationFrame() を提供することを決定しました。また、このメソッドはブラウザ レベルでより適切に最適化することもできます。ただし、これはアニメーション用の基本的な API にすぎません。つまり、DOM 要素のスタイル変更に基づくものではなく、canvas や WebGL に基づくものでもありません。したがって、特定のアニメーションの詳細を自分で記述する必要があります。

なぜそれを使用する必要があるのでしょうか?
同時に実行される n 個のアニメーションに対して、ブラウザは元の N 回のリフローと再描画を 1 回に最適化して、高品質のアニメーションを実現します。たとえば、JS ベースのアニメーション、CSS ベースのトランジション、または SVG SMIL があり、ブラウザーのタブでそのようなアニメーションが実行されている場合、別のタブに切り替えるか、単純に最小化します。表示できない場合、ブラウザはアニメーションを停止します。これにより、CPU、GPU、メモリの消費量が減り、バッテリー寿命が大幅に長くなります。

使い方は?

コードをコピー コードは次のとおりです:

// setTimeout を使用したシム層フォールバック
window.requestAnimFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
ウィンドウ.msRequestAnimationFrame |
function(/* 関数 */ コールバック, /* DOMElement */ 要素){
window.setTimeout(コールバック,
}); ;
// 使用法:
// setInterval(render, 16) の代わりに ....
(function animloop(){
render();
requestAnimFrame(animloop, element) ;
})();

注: 仕様はまだ変更中であり、仕様に左右されたくないため、ここでは「requestAnimFrame」を使用しました。
requestAnimationFrame API

コードをコピー コードは次のとおりです。
window.requestAnimationFrame( function(/ * time */ time){
// time ~= new Date // UNIX 時間
}, /* オプションの境界要素 */ elem);

Give最初の Chrome と Firefox バージョン

コードをコピー コードは次のとおりです。
window.mozRequestAnimationFrame( [callback]) ; // Firefox
window.webkitRequestAnimationFrame(callback[, element]) // Chrome

パラメータ:
callback: (FF はオプション、Chrome は必須)
Next repaint によって呼び出される関数、関数の最初のパラメーターは現在の時間です。
要素: (FF None)
言い換えましょう。これは実際にはキャンバスであり、「ペイント」はアニメーションです。 (アニメーション全体を視覚的に境界付ける要素)。 Canvas と WebGL の場合、これは 要素です。少し最適化したい場合は、これを無視することもできます。


それは信頼できますか? Webkit 実装 (Nightly Safari および Chrome Dev Channel で利用可能) と Mozilla 実装 (FF4 で利用可能) の間にはいくつかの違いがあり、Mozilla 実装にはバグがあります。実際、FF アニメーションのフレーム数は、1000/(16 N) fps のように計算されます。ここで、N はコールバックの実行時間 (ミリ秒) です。コールバックの実行時間が 1000 ミリ秒の場合、最高フレーム レートはわずか 1fps です。コールバックの実行時間が 1ms の場合、フレーム レートはほぼ 60fps になります。このバグはおそらく FF4 の次のバージョンで修正されるでしょう。 Chrome10 には時間パラメータがありません (m11 で追加されました。m11 とは何ですか?)。FF には現在要素パラメータがありません。
Firefox のバグを調べてみましたが、おそらく次のことを意味しています。
コールバックの実行時間が 1000/60 ミリ秒未満であっても、FF の mozRequestAnimationFrame() は 60fps に到達することができません。例:

コードをコピー コードは次のとおりです。
function callback(time) {
window.mozRequestAnimationFrame(callback);
doWork();


doWork() に 1000/60 ミリ秒かかる場合、フレーム レートは約 30 fps となり、同じアニメーションで setTimeout(callback, 16) を使用する場合、フレーム レートは 60 fps になります。コールバックは、コールバックの実行開始から 16 ミリ秒後ではなく、常に約 16 ミリ秒後に再度実行を開始するようです。後者の場合、計算が十分に高速であれば、60 fps フレームを生成できます。
標準コントロールの場合、ポータルはここにあります



早速、古典的なアニメーション関数から始めましょう:
コードをコピーします コードは次のとおりです:

function animate(element, name, from, to, time) {
time = time || //デフォルトは 0.8 秒
var style = element.style,
latency = 60, //60ms ごとに変更
count = time / latency, //変更の数
step = Math.round((to - from) / count), //各ステップの変化量
now = from;
function go() {
count--; 🎜>now = count ? now step : to;
style[name] = now 'px';
setTimeout(go, latency);
style [name] = from 'px';
setTimeout(go, latency);


この関数の設計上の制限に関係なく、単位は px でのみ設定できます。 スタイルを変更します。関数の実装だけの観点から見ると、これは非常に古典的なアニメーションの概念であり、その基本ロジックは次の部分で構成されます:
からの開始点の値と終了点の値、アニメーションに必要な時間、および各検出間の間隔 レイテンシー要件、値の変更回数と各変更ステップの量を計算します。
setTimeout(fn, latency) を有効にして次の検出に進みます。
次の検出では、属性ステップを一度設定します。アニメーションがまだ終了していない場合は、ステップ 2 に戻って次の検出を続けます。
この関数は非常にうまく機能し、何千ものサイトやシステムにサービスを提供しています。実際、jQuery の animate 関数の中核は setInterval 関数に他なりません。
しかし、現在のシステムの複雑さが着実に増加するにつれて、アニメーション効果がますます多くなり、アニメーションの滑らかさにさらに注意が払われるようになり、上記の機能にいくつかの問題が生じています。たとえば、上記の関数に従って 100 個のアニメーション効果を同時にオンにした場合、100 個のタイマーが同時に実行されることは明らかであり、これらのタイマー間のスケジュールはパフォーマンスにわずかな影響を与えます。通常の環境では、このような小さな効果は問題になりませんが、アニメーションなどの滑らかさが要求される環境では、わずかな影響がユーザー エクスペリエンスを悪化させる可能性があります。

そのような状況下で、一部の開発者は、タイマーを使用してアニメーション フレームをトリガーし、複数のアニメーション プロパティの変更を処理するためにこれらのフレームを登録します。この利点は、タイマー スケジュールのオーバーヘッドが軽減されることですが、アニメーション フレームワーク開発者にとっては、フレームを監視するための統合フレーム管理と API を開発および保守する必要があります。


ブラウザーの直接サポート

最終的に、ブラウザーのメーカーは、これが実際に自社で実行できることを発見し、ブラウザーのレベルに基づいて、さらに最適化できることがわかりました。たとえば、次のとおりです。
1 つの調査における DOM 上のすべての操作について、レイアウトとペイントは 1 回だけ実行されます。
アニメーション要素が非表示の場合、ペイントは実行されません。 その結果、ブラウザは requestAnimationFrame と呼ばれる API を起動するようになりました。この関数については、MDC の関連ページに詳しく説明されています。簡単に言うと、この関数を使用するには次の 2 つの方法があります。 requestAnimationFrame 関数を呼び出す。コールバック パラメータを渡すと、次のアニメーション フレームでコールバックが呼び出されます。
パラメータを渡さずにこの関数を直接呼び出してアニメーションフレームを開始すると、次のフレームがトリガーされると同時に window.onmozbeforepaint イベントがトリガーされます。このイベントを登録することでアニメーションを実行できます。

2 番目の方法は Firefox 独自のイベントに依存しており、beforepaint イベントはまだ標準に入っていないため、1 番目の方法を使用することをお勧めします。この時点で、アニメーション ロジックは次のようになります:
アニメーションの開始時刻として現在の時刻 startTime を記録します。
コールバック関数を使用して次のフレームをリクエストします。
次のフレームがトリガーされると、コールバック関数の最初のパラメーターは現在時刻であり、これが startTime と比較されて時間間隔 ellapseTime が決定されます。
ellapseTime が設定されたアニメーション時間を超えているかどうかを判断し、超えている場合はアニメーションを終了します。
アニメーション属性の変更の差分 = から - を計算し、ellapseTime = Different / time * ellapseTime の間にどのくらいのステップが変化するかを決定します。
現在変更すべきMath.round(from step)の位置を計算し、スタイルを再割り当てします。
次のフレームのリクエストを続けます。


新しいアニメーション関数

以下は新しいアニメーション関数です:


コードをコピー
コードは次のとおりです:

function animate(element, name, from, to, time) {
time = time || デフォルトは 0.8 秒
var style = element.style,
startTime = new Date;
function go(timestamp) {
var progress = timestamp - startTime;
if (progress >= period) {
style[name] = to
return;
}
var now = (to - from) * (進行状況 / 期間)
style[name] = now.toFixed() 'px';
requestAnimationFrame(go); 🎜>}
style[name] = from 'px';
requestAnimationFrame(go);
}

この時点で、次の問題が残っています。すべてのブラウザが requestAnimationFrame 関数をサポートしているわけではないので、簡単な修正を行ってください。
Firefox の特性により、mozRequestAnimationFrame が提供する最高 FPS は 60 であり、各フレームの計算時間に応じて調整されます。たとえば、各フレームの計算に 1 秒かかる場合、1FPS しか提供されません。アニメーション効果。
Chrome の上位バージョンでも、webkitRequestAnimationFrame と呼ばれるこの機能が実装されています。将来、Opera の oRequestAnimationFrame と IE の msRequestAnimationFrame が登場することが予想されます。そのため、簡単な互換性プロセスを次に示します:

コードをコピーします コードは次のとおりです:
requestAnimationFrame = window.requestAnimationFrame ||
window.mozRequestAnimationFrame || .webkitRequestAnimationFrame ||
window.oRequestAnimationFrame ||
function(callback, 1000 / 60) };
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。