4

I am working on a doodle in canvas,

I am running into an issue where when I erase the object by overdrawing it with the background color I am left with an outline of the original shape. enter image description here

Here is the code I am using

and yes I am not using clear rect because the circles can overlap.

    function erase(eraseColor) {
    ctx.fillStyle = ctx.strokeStyle = eraseColor || "#FFFFFF";
    drawCircle();
    ctx.fillStyle = ctx.strokeStyle = fillColor;
}

function drawCircle() {
    ctx.beginPath();
    ctx.arc(x, y, rad, 0, Math.PI * 2, true);
    ctx.closePath();
    ctx.fill();
}
samccone
  • 10,746
  • 7
  • 43
  • 50
  • This is probably due to anti-aliasing. Make the clear circles slightly larger (101% say) to make up for it. – Aaron Yodaiken Aug 07 '11 at 17:26
  • 1
    Do you think that will work when the circles overlap? I'm not so sure. Why not just stick with regular frame-based animation? – Ray Toal Aug 07 '11 at 17:33

1 Answers1

2

I believe this is due to anti-aliasing. The effect should not appear on shapes that do not require anti-aliasing (like rectangles). Draw the erasing circle a few pixels bigger (one should do).

In case the question comes up: you cannot turn off anti-aliasing for canvas.

As Ray suggested you should think about using frame based animation, optimized by using dirty rectangles.

To do this you simply flag a rectangle as dirty, if any pixels within it have changed (eg due to animation). You then clear the rectangle on the canvas (clearRect) and set it as a clipping rectangle (clip). Then you iterate through all elements that are displayed on your canvas and check wether they overlap with your dirty rectangle. If so, you draw the element, if not you skip to the next element.

Community
  • 1
  • 1
Daniel Baulig
  • 10,739
  • 6
  • 44
  • 43
  • 2
    +1 for the cause but with a lot of moving circles that may overlap each other any erase-by-drawing-a-background circle can't work. Animation should be done with frames (or optimized with dirty rectangles if necessary). – Ray Toal Aug 07 '11 at 17:35
  • frame based animation would be more costly erasing all the pixels then redrawing is much much much more inefficient then just overdrawing.. unless I am missing something – samccone Aug 07 '11 at 17:39
  • You can use dirty rectangles to minimize the amount of redrawing that is required. Simply flag a rectangle as "dirty", clear it and set it as clipping rectangle. Then check wether each element overlaps with this rectangle. If it does, draw it. Else check the next element. Rinse and repeat for each frame. – Daniel Baulig Aug 07 '11 at 17:43
  • 1
    With a lot of experience rendering animations in canvas, I think that this might be a case of premature optimization. Start by clearing the entire canvas and redrawing the entire frame. If you run into performance issues then starting looking at ways to optimize. In this case I think it would cost more to detect overlaps of dirty regions than to clear and redraw the entire canvas. – Prestaul Jul 01 '14 at 19:27