How to clear the canvas for redrawing

Viewed 1131638

After experimenting with composite operations and drawing images on the canvas I'm now trying to remove images and compositing. How do I do this?

I need to clear the canvas for redrawing other images; this can go on for a while so I don't think drawing a new rectangle every time will be the most efficient option.

24 Answers

Given that canvas is a canvas element or an OffscreenCanvas object,

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

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

If you are drawing lines, make sure you don't forget:

context.beginPath();

Otherwise the lines won't get cleared.

Others have already done an excellent job answering the question but if a simple clear() method on the context object would be useful to you (it was to me), this is the implementation I use based on answers here:

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();
    }           
};

Usage:

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
};

This is 2018 and still there is no native method to completely clear canvas for redrawing. clearRect() does not clear the canvas completely. Non-fill type drawings are not cleared out (eg. rect())

1.To completely clear canvas irrespective of how you draw:

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

Pros: Preserves strokeStyle, fillStyle etc.; No lag;

Cons: Unnecessary if you are already using beginPath before drawing anything

2.Using the width/height hack:

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

OR

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

Pros: Works with IE Cons: Resets strokeStyle, fillStyle to black; Laggy;

I was wondering why a native solution does not exist. Actually, clearRect() is considered as the single line solution because most users do beginPath() before drawing any new path. Though beginPath is only to be used while drawing lines and not closed path like rect().

This is the reason why the accepted answer did not solve my problem and I ended up wasting hours trying different hacks. Curse you mozilla

Use clearRect method by passing x,y co-ordinates and height and width of canvas. ClearRect will clear whole canvas as :

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

A quick way is to do

canvas.width = canvas.width

Idk how it works but it does!

This is what I use, regardless boundaries and matrix transformations:

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();
}

Basically, it saves the current state of the context, and draws a transparent pixel with copy as globalCompositeOperation. Then, restores the previous context state.

I always use

ctx.fillStyle = "rgb(255, 255, 255)";
ctx.fillRect(0, 0, canvas.width, canvas.height);

For a custom color, and

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

For making the canvas transparent when clearing

the shortest way:

canvas.width += 0
private clearCanvas() {
  const canvas: HTMLCanvasElement = this.ctx.canvas
  this.ctx.save()
  this.ctx.setTransform(1, 0, 0, 1, 0, 0)
  this.ctx.clearRect(0, 0, canvas.width, canvas.height)
  this.ctx.restore()
}
Context.clearRect(starting width, starting height, ending width, ending height);

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

I always use this

ctx.clearRect(0, 0, canvas.width, canvas.height)
window.requestAnimationFrame(functionToBeCalled)

NOTE

combining clearRect and requestAnimationFrame allows for more fluid animation if that is what you're going for

This is a Free hand drawing Canvas with a Clear Canvas Button.
See this live example of a canvas which you can draw on and also when required clear it for redrawing clearRect() is used to delete the prersent canvas and fillRect() is used to again draw the initial canvas which was clean and had no drawings on it.

var canvas = document.getElementById("canvas"),
    ctx = canvas.getContext("2d"),
    painting = false,
    lastX = 0,
    lastY = 0,
    lineThickness = 1;

canvas.width=canvas.height = 250;
ctx.fillRect(0, 0, 250, 250);

canvas.onmousedown = function(e) {
    painting = true;
    ctx.fillStyle = "#ffffff";
    lastX = e.pageX - this.offsetLeft;
    lastY = e.pageY - this.offsetTop;
};

canvas.onmouseup = function(e){
    painting = false;
}

canvas.onmousemove = function(e) {
    if (painting) {
        mouseX = e.pageX - this.offsetLeft;
        mouseY = e.pageY - this.offsetTop;

        // find all points between        
        var x1 = mouseX,
            x2 = lastX,
            y1 = mouseY,
            y2 = lastY;


        var steep = (Math.abs(y2 - y1) > Math.abs(x2 - x1));
        if (steep){
            var x = x1;
            x1 = y1;
            y1 = x;

            var y = y2;
            y2 = x2;
            x2 = y;
        }
        if (x1 > x2) {
            var x = x1;
            x1 = x2;
            x2 = x;

            var y = y1;
            y1 = y2;
            y2 = y;
        }

        var dx = x2 - x1,
            dy = Math.abs(y2 - y1),
            error = 0,
            de = dy / dx,
            yStep = -1,
            y = y1;

        if (y1 < y2) {
            yStep = 1;
        }

        lineThickness = 4;

        for (var x = x1; x < x2; x++) {
            if (steep) {
                ctx.fillRect(y, x, lineThickness , lineThickness );
            } else {
                ctx.fillRect(x, y, lineThickness , lineThickness );
            }

            error += de;
            if (error >= 0.5) {
                y += yStep;
                error -= 1.0;
            }
        }



        lastX = mouseX;
        lastY = mouseY;

    }
}
var button=document.getElementById("clear");
button.onclick=function clearcanvas(){
  canvas=document.getElementById("canvas"),
  ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, 250, 250);
canvas.width=canvas.height = 250;
ctx.fillRect(0, 0, 250, 250);}
#clear{border-radius:10px;
font-size:8px !important;
position:absolute;
top:1px;}
#canvas{border-radius:10px}
<link href="https://www.w3schools.com/w3css/4/w3.css" rel="stylesheet"/>
<button id="clear" class="w3-padding w3-xxlarge w3-pink" type="button">Clear Canvas</button>
<canvas id="canvas"></canvas>

These are all great examples of how you clear a standard canvas, but if you are using paperjs, then this will work:

Define a global variable in JavaScript:

var clearCanvas = false;

From your PaperScript define:

function onFrame(event){
    if(clearCanvas && project.activeLayer.hasChildren()){
        project.activeLayer.removeChildren();
        clearCanvas = false;
    }
}

Now wherever you set clearCanvas to true, it will clear all the items from the screen.

Related