web-dev-qa-db-ja.com

再描画のためにキャンバスを消去する方法

キャンバスに合成操作をしてイメージを描画した後、イメージを削除して合成を試みます。どうやってこれをするの?

他の画像を再描画するためにキャンバスをクリアする必要があります。これはしばらく続くことがあるので、毎回新しい長方形を描くことが最も効率的な選択肢になるとは思わない。

887
richard
const context = canvas.getContext('2d');

context.clearRect(0, 0, canvas.width, canvas.height);
1113
Pentium10

使用する:context.clearRect(0, 0, canvas.width, canvas.height);

これは、キャンバス全体を消去するための最も速くて説明的な方法です。

使用しないでください:canvas.width = canvas.width;

canvas.widthをリ​​セットすると、すべてのキャンバスの状態(例:変換、lineWidth、strokeStyleなど)がリセットされます。これは(clearRectと比較して)非常に遅く、すべてのブラウザで機能するわけではなく、実際にやろうとしていることを表しません。 。

変換された座標を扱う

変換行列を変更した場合(例えばscalerotate、またはtranslateを使用)、context.clearRect(0,0,canvas.width,canvas.height)はキャンバスの表示部分全体を消去しない可能性があります。

ソリューション?キャンバスを消去する前に変換行列をリセットします。

// Store the current transformation matrix
context.save();

// Use the identity matrix while clearing the canvas
context.setTransform(1, 0, 0, 1, 0, 0);
context.clearRect(0, 0, canvas.width, canvas.height);

// Restore the transform
context.restore();

編集: プロファイリングをしたところで、(Chromeでは)変換をリセットせずに300 x 150(デフォルトサイズ)のキャンバスをクリアするのが約10%速くなりました。キャンバスのサイズが大きくなると、この差は小さくなります。

これはすでに比較的重要ではありませんが、ほとんどの場合、クリアするよりもかなり多く描画することになります。このパフォーマンスの違いは無関係だと思います。

100000 iterations averaged 10 times:
1885ms to clear
2112ms to reset and clear
691
Prestaul

線を描いている場合は、忘れないでください。

context.beginPath();

そうでなければ、行はクリアされません。

210
trembl

他の人たちはすでにその質問に答えて優れた仕事をしてきましたが、コンテキストオブジェクトの単純なclear()メソッドがあなたにとって役に立つなら(これは私にとっても)、これは私がここで答えに基づいて使う実装です:

CanvasRenderingContext2D.prototype.clear = 
  CanvasRenderingContext2D.prototype.clear || function (preserveTransform) {
    if (preserveTransform) {
      this.save();
      this.setTransform(1, 0, 0, 1, 0, 0);
    }

    this.clearRect(0, 0, this.canvas.width, this.canvas.height);

    if (preserveTransform) {
      this.restore();
    }           
};

使用法:

window.onload = function () {
  var canvas = document.getElementById('canvasId');
  var context = canvas.getContext('2d');

  // do some drawing
  context.clear();

  // do some more drawing
  context.setTransform(-1, 0, 0, 1, 200, 200);
  // do some drawing with the new transform
  context.clear(true);
  // draw more, still using the preserved transform
};
114
JonathanK
  • Chromeは@ Pentium10によって示唆されているようにcontext.clearRect ( x , y , w , h );によく反応しますが、IE9はこの命令を完全に無視するようです。
  • IE9は次のように応答しているようです:canvas.width = canvas.width;しかし、@ John Allsoppの最初に幅を変更するという解決策を使用しない限り、線、図形、写真、その他のオブジェクトは消去されません。

キャンバスとコンテキストが次のように作成されているとします。

var canvas = document.getElementById('my-canvas');
var context = canvas.getContext('2d');

あなたはこのような方法を使用することができます:

function clearCanvas(context, canvas) {
  context.clearRect(0, 0, canvas.width, canvas.height);
  var w = canvas.width;
  canvas.width = 1;
  canvas.width = w;
}
35
grenade

X、y座標、キャンバスの高さと幅を渡して、clearRectメソッドを使用します。 ClearRectはキャンバス全体を次のようにクリアします。

canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
19
Vishwas

ここにはたくさんの良い答えがあります。もう1つ注意が必要なのは、キャンバスを部分的にクリアすることだけが楽しいことです。つまり、前の画像を完全に消去するのではなく、「フェードアウト」します。これはニーストレイル効果を与えることができます。

それは簡単です。背景色が白だとします。

// assuming background color = white and "eraseAlpha" is a value from 0 to 1.
myContext.fillStyle = "rgba(255, 255, 255, " + eraseAlpha + ")";
myContext.fillRect(0, 0, w, h);
14
orion elenzil

これは2018年ですが、それでも再描画のためにキャンバスを完全に消去するネイティブな方法はありません。 clearRect() はします キャンバスを完全にクリアしません。塗りつぶし以外の図面はクリアされません(例:rect()

1. to 完全に あなたが描く方法に関係なく、キャンバスをクリアする:

context.clearRect(0, 0, context.canvas.width, context.canvas.height);
context.beginPath();

長所:strokeStyle、fillStyleなどを保持します。遅れはありません。

短所:何かを描画する前にbeginPathを既に使用している場合は不要です。

2.幅/高さのハックを使う:

context.canvas.width = context.canvas.width;

OR

context.canvas.height = context.canvas.height;

長所:IEと連携します_短所:strokeStyle、fillStyleを黒にリセットします。遅れます。

私はなぜネイティブソリューションが存在しないのか疑問に思いました。実際、ほとんどのユーザーは新しいパスを描く前にclearRect()を実行するため、beginPath()は単一行のソリューションと見なされます。 beginPathは線を描画するときにのみ使用され、rect().のような閉じたパスは使用されません。

これが、受け入れられた答えが私の問題を解決しなかった理由であり、私は別のハックを試すのに何時間も無駄にしました。あなたのモジラを呪いなさい

14
sziraqui

簡単な方法は

canvas.width = canvas.width

Idkそれはどのように動作しますが、それはします!

7
Jacob Morris

私がテストしたすべてのブラウザで、最速の方法は実際に白または塗りつぶしの色で塗りつぶすことです。私は非常に大きなモニタを持っていて、フルスクリーンモードではclearRectが非常に遅くなっていますが、fillRectは妥当です。

context.fillStyle = "#ffffff";
context.fillRect(0,0,canvas.width, canvas.height);

欠点は、キャンバスが透明ではなくなったことです。

4
John Page

これはchart.jsの私のpieChartのために働きました

<div class="pie_nut" id="pieChartContainer">
    <canvas id="pieChart" height="5" width="6"></canvas> 
</div>

$('#pieChartContainer').html(''); //remove canvas from container
$('#pieChartContainer').html('<canvas id="pieChart" height="5" width="6"></canvas>'); //add it back to the container
4
Sanal S
function clear(context, color)
{
    var tmp = context.fillStyle;
    context.fillStyle = color;
    context.fillRect(0, 0, context.canvas.width, context.canvas.height);
    context.fillStyle = tmp;
}
4
Imagine Breaker

webKitでは、幅を別の値に設定する必要があります。その後、初期値に戻すことができます。

4
John Allsopp

これは私が使っているものですが、境界や行列の変換は関係ありません。

function clearCanvas(canvas) {
  const ctx = canvas.getContext('2d');
  ctx.save();
  ctx.globalCompositeOperation = 'copy';
  ctx.strokeStyle = 'transparent';
  ctx.beginPath();
  ctx.lineTo(0, 0);
  ctx.stroke();
  ctx.restore();
}

基本的には、コンテキストの現在の状態を保存し、 copy としてglobalCompositeOperationを使って透明なピクセルを描画します。その後、前のコンテキスト状態を復元します。

3
superruzafa

最速の方法:

canvas = document.getElementById("canvas");
c = canvas.getContext("2d");

//... some drawing here

i = c.createImageData(canvas.width, canvas.height);
c.putImageData(i, 0, 0); // clear context by putting empty image data
2
elser

簡単ですが、あまり読みやすい方法ではありません。

var canvas = document.getElementId('canvas');

// after doing some rendering

canvas.width = canvas.width;  // clear the whole canvas
2
Chang

私はいつも使う

cxt.fillStyle = "rgb(255, 255, 255)";
cxt.fillRect(0, 0, canvas.width, canvas.height);
0
GameMaster1928
Context.clearRect(starting width, starting height, ending width, ending height);

例:context.clearRect(0, 0, canvas.width, canvas.height);

0
Gavin T
context.clearRect(0,0,w,h)   

与えられた長方形をRGBA値で塗りつぶします。
0 0 0 0:Chromeあり
0 0 0 255:FF付き&サファリ

しかし

context.clearRect(0,0,w,h);    
context.fillStyle = 'rgba(0,0,0,1)';  
context.fillRect(0,0,w,h);  

四角形を塗りつぶす
0 0 0 255
ブラウザに関係なく!

ClearRectのみを使用している場合、図面を送信するためのフォームに含めると、クリアの代わりに送信されるか、最初にクリアしてから無効な図面をアップロードできるため、関数の開始時にpreventDefault:

   function clearCanvas(canvas,ctx) {
        event.preventDefault();
        ctx.clearRect(0, 0, canvas.width, canvas.height);
    }


<input type="button" value="Clear Sketchpad" id="clearbutton" onclick="clearCanvas(canvas,ctx);">

誰かに役立つことを願っています。

0
JoelBonetR