Clearing a strokeRect() on HTML5 Canvas

d m picture d m · Oct 3, 2014 · Viewed 10.9k times · Source

I can draw a square with a border on my canvas perfectly fine. However, when I attempt to clear this square-with-border shape using the clearRect() function, some strokes do not get cleared.

HTML

<div>
    <canvas width="300" height="250">
    </canvas>
</div>

JS

var $context = $('canvas')[0].getContext('2d');

// Create 4 filled squares
$context.fillStyle = 'pink';
$context.fillRect(120, 0, 30, 30);
$context.fillRect(120, 30, 30, 30);
$context.fillRect(150, 0, 30, 30);
$context.fillRect(150, 30, 30, 30);

// Create borders around them
$context.strokeRect(120, 0, 30, 30);
$context.strokeRect(120, 30, 30, 30);
$context.strokeRect(150, 0, 30, 30);
$context.strokeRect(150, 30, 30, 30);

// Now erase the squares (individually)
$context.clearRect(120, 0, 30, 30);
$context.clearRect(120, 30, 30, 30);
$context.clearRect(150, 0, 30, 30);
$context.clearRect(150, 30, 30, 30);

See the jsFiddle here.

After looking more carefully, it seems the clearRect() function doesn’t actually clear the stroke from my strokeRect() call. So I was thinking, maybe what I need to do is simply stroke the border with a strokeStyle of ‘white’. However, when I do this (new fiddle here), it seems like this paints a white stroke but only with an alpha value of 128! My globalAlpha is set to 1…shouldn’t this be completely opaque?

What am I not understanding here? Does the clearRect() not clear calls to strokeRect()? And if not, should the solution be stroking over the existing strokeRect() but with a color of white?

Note that I cannot simply just clear the canvas but must clear one square at a time.

Thanks in advance!

Answer

Michal picture Michal · Oct 3, 2014

Things are working correctly. Borders via strokeRect add height and width to the shape equal to the lineWidth. clearRect isn't a fancy function, it just works like an eraser - removing "paint" only from the area you specify.

In your example, the lineWidth is the default of 1. Your code draws rectangles of 30x30, and then applies a border via stroke of width 1. The resulting shape is 32x32 - resulting from 1 + 30 + 1.

To clear this whole thing, you have to tweak your math a bit:

$context.clearRect(119, -1, 32, 32);
$context.clearRect(119, 29, 32, 32);
$context.clearRect(149, -1, 32, 32);
$context.clearRect(149, 29, 32, 32);

This moves over one x and one y coordinate, as well as increases the size of the clear to cover the border as well as the shape itself.

jsfiddle: http://jsfiddle.net/fg6fmjhb/2/