これらは、深く掘り下げるまで、理論的にはすべて良いアイデアです。 問題は、RAFを非同期化せずにRAFをスロットルすることができず、それを無効にすることが既存の目的であるということです。 あなたはそれがフルスピードで実行し、別のループでデータを更新しましょうだから、あるいは別のスレッド!
はい、私はそれを言った。あなたはできるブラウザでマルチスレッドJavaScriptを行います!
私が知っている2つの方法は、ジャンクなしで非常にうまく機能することです。はるかに少ないジュースを使用し、発熱を抑えます。正確な人間規模のタイミングと機械効率が最終的な結果です。
これは少し冗長ですが、ここに行きます...
方法1:setIntervalを介してデータを更新し、RAFを介してグラフィックを更新します。
移動と回転の値、物理、衝突などを更新するには、個別のsetIntervalを使用します。アニメーション化された要素ごとに、これらの値をオブジェクトに保持します。各setInterval 'frame'のオブジェクトの変数に変換文字列を割り当てます。これらのオブジェクトを配列に保持します。間隔をmsで希望するfpsに設定します:ms =(1000 / fps)。これにより、RAF速度に関係なく、任意のデバイスで同じfpsを可能にする安定したクロックが維持されます。 ここで要素に変換を割り当てないでください!
requestAnimationFrameループで、古い学校のforループを使用して配列を反復処理します。ここでは新しいフォームを使用しないでください。低速です。
for(var i=0; i<sprite.length-1; i++){ rafUpdate(sprite[i]); }
rafUpdate関数で、配列内のjsオブジェクトから変換文字列を取得し、その要素IDを取得します。変数にアタッチされているか、他の方法で簡単にアクセスできる「スプライト」要素がすでにあるはずなので、RAFで「取得」する時間を無駄にしないでください。それらのhtml idにちなんで名付けられたオブジェクトにそれらを保持することはかなりうまくいきます。SIまたはRAFに入る前に、その部分をセットアップします。
RAFを使用して、変換のみを更新し、3D変換のみ(2dの場合でも)を使用し、cssに "will-change:transform;"を設定します。変化する要素について。これにより、変換がネイティブリフレッシュレートに可能な限り同期され、GPUが起動し、ブラウザーに最も集中する場所を指示します。
したがって、この疑似コードのようなものが必要です...
// refs to elements to be transformed, kept in an array
var element = [
mario: document.getElementById('mario'),
luigi: document.getElementById('luigi')
//...etc.
]
var sprite = [ // read/write this with SI. read-only from RAF
mario: { id: mario ....physics data, id, and updated transform string (from SI) here },
luigi: { id: luigi .....same }
//...and so forth
] // also kept in an array (for efficient iteration)
//update one sprite js object
//data manipulation, CPU tasks for each sprite object
//(physics, collisions, and transform-string updates here.)
//pass the object (by reference).
var SIupdate = function(object){
// get pos/rot and update with movement
object.pos.x += object.mov.pos.x; // example, motion along x axis
// and so on for y and z movement
// and xyz rotational motion, scripted scaling etc
// build transform string ie
object.transform =
'translate3d('+
object.pos.x+','+
object.pos.y+','+
object.pos.z+
') '+
// assign rotations, order depends on purpose and set-up.
'rotationZ('+object.rot.z+') '+
'rotationY('+object.rot.y+') '+
'rotationX('+object.rot.x+') '+
'scale3d('.... if desired
; //...etc. include
}
var fps = 30; //desired controlled frame-rate
// CPU TASKS - SI psuedo-frame data manipulation
setInterval(function(){
// update each objects data
for(var i=0; i<sprite.length-1; i++){ SIupdate(sprite[i]); }
},1000/fps); // note ms = 1000/fps
// GPU TASKS - RAF callback, real frame graphics updates only
var rAf = function(){
// update each objects graphics
for(var i=0; i<sprite.length-1; i++){ rAF.update(sprite[i]) }
window.requestAnimationFrame(rAF); // loop
}
// assign new transform to sprite's element, only if it's transform has changed.
rAF.update = function(object){
if(object.old_transform !== object.transform){
element[object.id].style.transform = transform;
object.old_transform = object.transform;
}
}
window.requestAnimationFrame(rAF); // begin RAF
これにより、SIで目的の「フレーム」レートに同期されたデータオブジェクトと変換文字列への更新、およびGPUリフレッシュレートに同期されたRAFでの実際の変換割り当てが維持されます。そのため、実際のグラフィックスの更新はRAFでのみ行われますが、データへの変更と変換文字列の作成はSIで行われるため、ジャンキーではなく、希望のフレームレートで「時間」が流れます。
フロー:
[setup js sprite objects and html element object references]
[setup RAF and SI single-object update functions]
[start SI at percieved/ideal frame-rate]
[iterate through js objects, update data transform string for each]
[loop back to SI]
[start RAF loop]
[iterate through js objects, read object's transform string and assign it to it's html element]
[loop back to RAF]
方法2. SIをWebワーカーに配置します。これはFAAASTでスムーズです!
方法1と同じですが、SIをWebワーカーに配置します。その後、完全に別のスレッドで実行され、ページはRAFとUIのみを処理します。スプライト配列を「転送可能なオブジェクト」としてやり取りします。これは高速ブコです。複製やシリアライズに時間はかかりませんが、反対側からの参照が破棄されるという点で参照による受け渡しとは異なります。そのため、両側を反対側に渡し、存在する場合にのみそれらを更新する必要があります。高校でガールフレンドとノートをやり取りするようなものです。
一度に読み書きできるのは1人だけです。エラーを回避するために未定義でないかどうかを確認する限り、これは問題ありません。RAFは高速で、すぐにキックバックし、GPUフレームの束を調べて、まだ送り返されているかどうかを確認します。ほとんどの場合、WebワーカーのSIはスプライト配列を持ち、位置、動き、物理データを更新し、新しい変換文字列を作成して、ページのRAFに返します。
これは、スクリプトを使用して要素をアニメーション化するための最も速い方法です。2つの関数は、2つの別個のプログラムとして、2つの別個のスレッドで実行され、マルチコアCPUを活用することで、単一のjsスクリプトでは実現できません。マルチスレッドのJavaScriptアニメーション。
そして、それはジャンクなしでスムーズに行いますが、実際の指定されたフレームレートで、ほとんど発散しません。
結果:
これらの2つの方法のいずれかを使用すると、任意のPC、電話、タブレットなどで(もちろん、デバイスとブラウザーの機能内で)スクリプトが同じ速度で実行されます。
requestAnimationFrame
は、(名前の種類が示唆するように)必要なときにのみアニメーションフレームを要求することです。静的な黒いキャンバスを表示するとします。新しいフレームは必要ないため、0 fpsになるはずです。ただし、60fpsを必要とするアニメーションを表示している場合は、それも取得する必要があります。rAF
不要なフレームを「スキップ」してCPUを節約するだけです。