私がやりたいのは、グラフィックをバッファに描画し、それをそのままキャンバスにコピーして、アニメーションを実行し、ちらつきを回避できるようにすることです。しかし、私はこのオプションを見つけることができませんでした。誰かが私がこれについてどうやって行くことができるか知っていますか?
explorercanvas
が、これはもちろんHTML5ではcanvas
なく、VMLによってエミュレートされた要素にすぎません。しかし、他のブラウザがそれを行うのを見たことがありません。
私がやりたいのは、グラフィックをバッファに描画し、それをそのままキャンバスにコピーして、アニメーションを実行し、ちらつきを回避できるようにすることです。しかし、私はこのオプションを見つけることができませんでした。誰かが私がこれについてどうやって行くことができるか知っていますか?
explorercanvas
が、これはもちろんHTML5ではcanvas
なく、VMLによってエミュレートされた要素にすぎません。しかし、他のブラウザがそれを行うのを見たことがありません。
回答:
次の役立つリンクは、ダブルバッファリングを使用する例と利点を示すことに加えて、html5キャンバス要素を使用するための他のいくつかのパフォーマンスのヒントを示しています。これには、ブラウザ全体のテスト結果をBrowserscopeデータベースに集約するjsPerfテストへのリンクが含まれています。これにより、パフォーマンスのヒントが確実に検証されます。
http://www.html5rocks.com/en/tutorials/canvas/performance/
便宜上、記事で説明されている効果的なダブルバッファリングの最小限の例を含めました。
// canvas element in DOM
var canvas1 = document.getElementById('canvas1');
var context1 = canvas1.getContext('2d');
// buffer canvas
var canvas2 = document.createElement('canvas');
canvas2.width = 150;
canvas2.height = 150;
var context2 = canvas2.getContext('2d');
// create something on the canvas
context2.beginPath();
context2.moveTo(10,10);
context2.lineTo(10,30);
context2.stroke();
//render the buffered canvas onto the original canvas element
context1.drawImage(canvas2, 0, 0);
非常に簡単な方法は、同じ画面位置に2つのcanvas要素を配置し、表示する必要のあるバッファーの可視性を設定することです。隠されたものを描き、終わったら裏返します。
いくつかのコード:
CSS:
canvas { border: 2px solid #000; position:absolute; top:0;left:0;
visibility: hidden; }
JSでの反転:
Buffers[1-DrawingBuffer].style.visibility='hidden';
Buffers[DrawingBuffer].style.visibility='visible';
DrawingBuffer=1-DrawingBuffer;
このコードでは、配列 'Buffers []'は両方のcanvas-objectsを保持します。したがって、描画を開始する場合でも、コンテキストを取得する必要があります。
var context = Buffers[DrawingBuffer].getContext('2d');
<noscript>
、Javascriptでキャンバス要素を作成するのが好きです。とにかく、通常はJavascriptでキャンバスのサポートを確認する必要があるのに、なぜHTMLにキャンバスのフォールバックメッセージを入れたいのでしょうか。
私がテストしたブラウザはすべて、フレームを描画するコードが完了するまでキャンバスを再描画しないことで、このバッファリングを処理します。WHATWGメーリングリストも参照してください:http://www.mail-archive.com/whatwg@lists.whatwg.org/msg19969.html
いつでも実行できvar canvas2 = document.createElement("canvas");
、DOMに追加することはできません
。
皆さんがとても夢中にdisplay:none;
なっているように見えるので、私にはすっきりしているように見え、ぎこちなく見えないキャンバスを持っているよりも正確にダブルバッファリングのアイデアを模倣しています。
2年以上後:
「手動で」ダブルバッファリングを実装する必要はありません。Geary氏は、彼の著書「HTML5Canvas」でこれについて書いています。
ちらつきを効果的に減らすためにrequestAnimationFrame()
!
Joshは、ちらつきを避けるために、ブラウザが「描画プロセスがいつ終了するか」をどのように知っているかについて(しばらく前に)尋ねました。私は彼の投稿に直接コメントしたでしょうが、私の担当者は十分に高くありません。また、これは私の意見です。私はそれを裏付ける事実を持っていませんが、私はそれについてかなり自信を持っており、将来これを読んでいる他の人に役立つかもしれません。
描画が完了したとき、ブラウザは「認識」していないと思います。ただし、ほとんどのJavaScriptと同様に、コードがブラウザーへの制御を放棄せずに実行される限り、ブラウザーは基本的にロックされ、UIを更新/更新/応答できません。ブラウザの制御を放棄せずにキャンバスをクリアしてフレーム全体を描画すると、完了するまで実際にはキャンバスが描画されないと思います。
レンダリングが複数のsetTimeout / setInterval / requestAnimationFrame呼び出しにまたがる状況を設定した場合、1回の呼び出しでキャンバスをクリアし、次の数回の呼び出しでキャンバスに要素を描画し、(たとえば)5回の呼び出しごとにサイクルを繰り返します。呼び出しのたびにキャンバスが更新されるため、ちらつきが表示されることは間違いありません。
とはいえ、それを信頼できるかどうかはわかりません。私たちはすでに、実行前にjavascriptがネイティブマシンコードにコンパイルされる段階にあります(少なくとも、私が理解していることから、ChromeのV8エンジンはそれを実行します)。ブラウザがUIとは別のスレッドでJavaScriptを実行し、UI要素へのアクセスを同期して、UIにアクセスしていないJavaScriptの実行中にUIを更新/応答できるようになるまで、それほど長くはかからなかったとしても、驚くことではありません。それが発生した場合(そして、他のコードを実行しているときにイベントハンドラーが開始されるなど、克服しなければならない多くのハードルがあることを理解しています)、使用していないキャンバスアニメーションでちらつきが発生する可能性がありますある種のダブルバッファリング。
個人的には、2つのキャンバス要素を重ねて配置し、各フレームに表示/描画するというアイデアが大好きです。かなり邪魔にならず、おそらく数行のコードで既存のアプリケーションに簡単に追加できます。
不信者のために、ここにいくつかのちらつきコードがあります。前の円を消去することを明示的にクリアしていることに注意してください。
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
function draw_ball(ball) {
ctx.clearRect(0, 0, 400, 400);
ctx.fillStyle = "#FF0000";
ctx.beginPath();
ctx.arc(ball.x, ball.y, 30, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fill();
}
var deltat = 1;
var ball = {};
ball.y = 0;
ball.x = 200;
ball.vy = 0;
ball.vx = 10;
ball.ay = 9.8;
ball.ax = 0.1;
function compute_position() {
if (ball.y > 370 && ball.vy > 0) {
ball.vy = -ball.vy * 84 / 86;
}
if (ball.x < 30) {
ball.vx = -ball.vx;
ball.ax = -ball.ax;
} else if (ball.x > 370) {
ball.vx = -ball.vx;
ball.ax = -ball.ax;
}
ball.ax = ball.ax / 2;
ball.vx = ball.vx * 185 / 186;
ball.y = ball.y + ball.vy * deltat + ball.ay * deltat * deltat / 2
ball.x = ball.x + ball.vx * deltat + ball.ax * deltat * deltat / 2
ball.vy = ball.vy + ball.ay * deltat
ball.vx = ball.vx + ball.ax * deltat
draw_ball(ball);
}
setInterval(compute_position, 40);
<!DOCTYPE html>
<html>
<head><title>Basketball</title></head>
<body>
<canvas id="myCanvas" width="400" height="400" style="border:1px solid #c3c3c3;">
Your browser does not support the canvas element.
</canvas>
</body></html>
Webブラウザにちらつきはありません!彼らはすでにレンダリングにdblバッファリングを使用しています。Jsエンジンは、表示する前にすべてのレンダリングを行います。また、コンテキストは、キャンバスコンテンツ自体ではなく、スタック変換行列データなどのみを保存および復元します。したがって、dblバッファリングは必要ありません。
自分で作成するのではなく、既存のライブラリを使用してクリーンでちらつきのないJavaScriptアニメーションを作成することで、おそらく最高のマイレージを得ることができます。
これが人気のあるものです:http://processingjs.org
2つのキャンバスが必要です:(css z-indexとposition:absoluteに注意してください)
<canvas id="layer1" width="760" height="600" style=" position:absolute; top:0;left:0;
visibility: visible; z-index: 0; solid #c3c3c3;">
Your browser does not support the canvas element.
</canvas>
<canvas id="layer2" width="760" height="600" style="position:absolute; top:0;left:0;
visibility: visible; z-index: 1; solid #c3c3c3;">
Your browser does not support the canvas element.
</canvas>
最初のキャンバスが表示され、2番目のキャンバスが非表示になっていることがわかります。その後、非表示に描画するというアイデアを非表示にして、非表示のキャンバスを表示します。それが隠されているとき '明確な隠されたキャンバス
<script type="text/javascript">
var buff=new Array(2);
buff[0]=document.getElementById("layer1");
buff[1]=document.getElementById("layer2");
ctx[0]=buff[0].getContext("2d");
ctx[1]=buff[1].getContext("2d");
var current=0;
// draw the canvas (ctx[ current ]);
buff[1- current ].style.visibility='hidden';
buff[ current ].style.visibility='visible';
ctx[1-current].clearRect(0,0,760,600);
current =1-current;
Opera 9.10は非常に遅く、描画プロセスを示しています。ブラウザがダブルバッファリングを使用しないようにしたい場合は、Opera9.10を試してみてください。
一部の人々は、ブラウザが描画プロセスがいつ終了するかを何らかの形で決定していると示唆しましたが、それがどのように機能するかを説明できますか?Firefox、Chrome、IE9では、描画が遅い場合でも明らかなちらつきに気づかなかったので、それが彼らのやっているように見えますが、それがどのように達成されるかは私には謎です。さらに描画命令が実行される直前に、ブラウザが表示を更新していることをどのようにして知ることができますか?キャンバス描画命令を実行せずに5ms以上の間隔が経過した場合、バッファを安全に交換できると想定しているので、ちょうどいいタイミングだと思いますか?
ほとんどの場合、これを行う必要はありません。ブラウザがこれを実装します。しかし、常に役立つとは限りません!
図面が非常に複雑な場合でも、これを実装する必要があります。ほとんどの画面更新レートは約60Hzで、16msごとに画面が更新されることを意味します。ブラウザの更新レートはこの数値に近い可能性があります。シェイプを完成させるのに100msが必要な場合は、未完成のシェイプが表示されます。したがって、この状況でダブルバッファリングを実装できます。
テストを行いました。Clear a rect, wait for some time, then fill with some color.
時間を10msに設定すると、ちらつきは見られません。しかし、20msに設定すると、ちらつきが発生します。