質問

私がやりたいのは、グラフィックをバッファ上に描画し、それをそのままキャンバスにコピーできるようにして、アニメーションを実行してちらつきを回避できるようにすることです。しかし、このオプションが見つかりませんでした。どうすればよいか知っている人はいますか?

役に立ちましたか?

解決

次の有用なリンクは、ダブルバッファリングの使用の例と利点を示すことに加えて、HTML5キャンバス要素を使用するための他のいくつかのパフォーマンスのヒントを示しています。これには、ブラウザ全体でテスト結果をブラウザースコープデータベースに集約する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つのキャンバス要素を置き、表示する必要があるバッファーの可視性を設定することです。完了したら、隠されたフリップを描きます。

いくつかのコード:

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;

このコードでは、配列 'バッファ[]'は両方のCanvas-Objectsを保持します。したがって、描画を開始したい場合は、コンテキストを取得する必要があります。

var context = Buffers[DrawingBuffer].getContext('2d');

ブラウザは、フレームを描画するコードが完成するまでキャンバスを再挿入しないことにより、このバッファリングをすべて処理しました。 whatwgメーリングリストも参照してください: http://www.mail-archive.com/whatwg@lists.whatwg.org/msg19969.html

あなたはいつでもできますvar canvas2 = document.createElement("canvas");そして、それをDOMにまったく追加しないでください。

あなたたちがとても夢中になっているように見えるので、ただ言っているだけです display:none;それは私にはきれいに思え、ぎこちなく見えないキャンバスを持っているよりも、ダブルバッファリングの方法をより正確に模倣するという考えを模倣しています。

2年以上後:

ダブルバッファリングを「手動で」実装する必要はありません。ギアリー氏は彼の本でこれについて書いた 「HTML5キャンバス」.

ちらつきの使用を効果的に減らすため requestAnimationFrame()!

ジョシュは(しばらく前に)、ブラウザーが「図面プロセスが終了したとき」をどのように知っているかを尋ね、フリッカーを避けました。私は彼の投稿に直接コメントしたでしょうが、私の担当者は十分に高くありません。また、これは私の意見です。私はそれをバックアップする事実を持っていませんが、私はそれについてかなり自信を持っていると感じており、将来これを読んでいる他の人に役立つかもしれません。

描画が完了したときにブラウザが「わからない」と推測しています。しかし、ほとんどのJavaScriptと同様に、ブラウザのコントロールを放棄せずにコードが実行されている限り、ブラウザは本質的にロックされており、UIに更新/応答しません。ブラウザへのコントロールを放棄せずにキャンバスをクリアしてフレーム全体を描くと、実際にキャンバスを描画しないと推測しています。

レンダリングが複数のSettimeOut/SetInterval/RequestAnimationFrameコールにまたがる状況を設定し、1つの呼び出しでキャンバスをクリアし、次のいくつかの呼び出しでキャンバスに要素を描画し、5つの呼び出しごとにサイクルを繰り返します。 '各呼び出しの後にキャンバスが更新されるので、あなたはフリッカーを見ることに賭けてください。

そうは言っても、私はそれを信頼するかどうかわかりません。私たちはすでに、JavaScriptが実行前にネイティブマシンコードにコンパイルされている時点にいます(少なくとも、それはChromeのV8エンジンが私が理解していることからしていることです)。ブラウザがUIとは別のスレッドでJavaScriptの実行を開始し、UI要素へのアクセスを同期してUIがUIにアクセスしていないJavaScript実行中に更新/応答できるようにするのがそれほど長くなかったとしても驚かないでしょう。それが起こったとき(そして、私はあなたがまだ他のコードを実行している間にイベントハンドラーがキックオフするなど、克服しなければならない多くのハードルがあることを理解しています)ある種のダブルバッファリング。

個人的には、私は互いの上に位置する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エンジンは、それを表示する前にすべてのレンダリングを作成します。また、コンテキストは、Canvasコンテンツ自体ではなく、スタック変換マトリックスデータなどのみを保存および復元します。したがって、DBLバッファリングを必要としないか、必要としません!

自分で転がすのではなく、既存のライブラリを使用してクリーンでフリーフリーのJavaScriptアニメーションを作成することで、最高の走行距離を取得するでしょう。

これが人気のあるものです: http://processingjs.org

2つのキャンバスが必要です:( CSS z-indexと位置に注意してください:絶対)

<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 は非常に遅く、描画プロセスが表示されます。ダブルバッファリングを使用しないブラウザを確認したい場合は、Opera 9.10 を試してください。

ブラウザが描画プロセスの終了時期を何らかの方法で決定しているのではないかと言う人もいますが、それがどのように機能するのか説明していただけますか?Firefox、Chrome、または IE9 では、描画が遅い場合でも明らかなちらつきに気づかなかったので、そのようにしているようですが、どのようにしてそれが実現されるのかは私には謎です。ブラウザは、さらに描画命令が実行される直前に表示を更新していることをどのようにして知るのでしょうか?キャンバス描画命令が実行されずに 5 ミリ秒以上の間隔が経過した場合に、安全にバッファを交換できると見なすように、単に時間を計っているだけだと思いますか?

ほとんどの状況では、これを行う必要はありません。ブラウザはこれを実装しています。 しかし、常に有用ではありません!

描画が非常に複雑な場合でも、これを実装する必要があります。画面の更新率のほとんどは約60Hzで、画面が16msあたりの更新を意味します。ブラウザの更新レートは、この数に近い場合があります。形状を完了する必要がある場合は、未完成の形状が表示されます。したがって、この状況でダブルバッファリングを実装できます。

私はテストをしました: Clear a rect, wait for some time, then fill with some color. 時間を10ミリ秒に設定すると、ちらつきが見えません。しかし、私がそれを20msに設定すると、ちらつきが起こります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top