5

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!

braX
  • 11,506
  • 5
  • 20
  • 33
d m
  • 581
  • 3
  • 6
  • 8
  • 1
    `clearRect()` works fine. Stokes have a width to them when they are drawn. In both the outer and inner sides it was draw on. You just need to extend the `clearRect`. Also note that `stroke` has some alpha to them. – Spencer Wieczorek Oct 03 '14 at 03:56
  • @SpencerWieczorek - Not sure how to 'extend' the `clearRect()` function. I tried setting `lineWidth` to 2 instead of the default of 1 right before calling `clearRect()` but this doesn't amount to much. How specifically would you be setting the outer & inner sides for clearing the rectangle? – d m Oct 03 '14 at 04:15
  • Have `clearRect()` cover 1 more pixel in each direction. For example other that clearing a `30x30` area, clear `32x32`. – Spencer Wieczorek Oct 03 '14 at 04:24
  • When he says 'extend', @SpencerWieczorek means `clearRect(120-2, 0-2, 30+4, 30+4)`. BTW, html canvas workflow typically clears the canvas and redraws all desired shapes rather than trying to erase an existing drawing. As you've discovered, canvas makes erasing quite complicated. The key is to "remember" the shapes' definitions so they can be redrawn--usually in a javascript object. Cheers! – markE Oct 03 '14 at 04:28

3 Answers3

11

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/

Michal
  • 2,532
  • 1
  • 19
  • 27
3

clearReact wasn't working for me because I forgot to use beginPath before drawing lines. Use: context.beginPath();

So this will do:

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

$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);

// add this:
$context.beginPath();

$context.strokeRect(120, 0, 30, 30);
$context.strokeRect(120, 30, 30, 30);
$context.strokeRect(150, 0, 30, 30);
$context.strokeRect(150, 30, 30, 30);

$('.erase').on('click', function() {
    // Now erase everything
    $context.clearRect(0,0,$('canvas')[0].width, $('canvas')[0].height);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
    <canvas width="300" height="250"></canvas>
</div>
<button class="erase">Attempt to Clear</button>
Erick Hernández
  • 1,072
  • 1
  • 10
  • 11
1

You can also do this:

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

This will clear the canvas context completely.

Marcel Burkhard
  • 3,453
  • 1
  • 29
  • 35
Navya
  • 53
  • 9