1

I've made a canvas where I draw shapes on. When I want to delete them, I basically create the same shape again but it's white, so I don't delete any other shapes (saved the x and y coordinate, so nothing to worry there)

ctx.fillStyle="#FFFFFF";
ctx.strokeStyle="#FFFFFF";

ctx.beginPath();
ctx.arc(x, y, 40, 0, 2 * Math.PI);
ctx.fill();

The problem is that on some shapes there is still a remaining black rest, that I can't get rid of (it's even worse on other shapes)

What Am I missing?

var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');

ctx.beginPath();
ctx.arc(50,50 , 40, 0, 2 * Math.PI);
ctx.fill();
          
ctx.fillStyle="#FFFFFF";
ctx.strokeStyle="#FFFFFF";
      
ctx.beginPath();
ctx.arc(50,50 , 40, 0, 2 * Math.PI);
ctx.fill();
<canvas id="myCanvas" width="1000" height=600 style="border: 1px solid #000000;">
</canvas>

EDIT: https://jsfiddle.net/sfj5y091/3/

EDIT 2: I solved this problem in the end, by completely redrawing all the shapes after one shape was deleted in the system, which even enabled the deletion of shapes that overlapped without destroying the other shape

  • 2
    Can you make us a basic working example? Maybe in JSFiddle or even in the [StackOverflow Code example editor](http://prntscr.com/lgcv47)? – Fusseldieb Nov 09 '18 at 15:47
  • you should use clear overpainting is not the way to go. maybe this helps https://stackoverflow.com/questions/10396991/clearing-circular-regions-from-html5-canvas – L.A Nov 09 '18 at 15:48
  • canvas is really not equipped to deal with considering the drawings as seperate objects. Instead of redrawing, it's probably better to just save the previous states and rerender those, instead of adding even more drawings on top of the canvas. If you really have to be able to work with drawn things seperately, SVG is better equipped to do that. – Shilly Nov 09 '18 at 15:48
  • You could have 2 canvas (one behind the other) and you could keep the information about the shape you're drawing in a structure. When you have to erase a shape, you simply redraw all the the shapes execpt for the one erased on the second canvas. To show the second canvas put a CSS z-index property bigger than the first canvas. This is called [Double buffering](https://en.wikipedia.org/wiki/Multiple_buffering) – Dominique Fortin Nov 09 '18 at 15:49
  • I added a jsfiddle, so you can see what I mean! It's just the remaining parts that I want to get rid of! – l33t5p34k3r Nov 09 '18 at 15:53
  • 1
    @Fusseldieb thx for pointing out, that there is a StackOverflow Editor, this Website is awesome – l33t5p34k3r Nov 09 '18 at 15:57
  • Much better now :) – Fusseldieb Nov 09 '18 at 15:57
  • canvas and the overpainting itself are no discussable, because of project requirements.. but thanks for the answers! – l33t5p34k3r Nov 09 '18 at 16:07

2 Answers2

1

The residue is caused by smoothing or anti-aliasing.

To draw the black circle on the initially white background, an "aura" of gray pixels is drawn at the edge of the 40-pixel-radius circle to give it a smooth appearance, and that "aura" is a tiny bit bigger than what you planned to draw.

If you then draw a white 40-pixel-radius circle on top of that, it blends the new white edge pixels with what is now a non-white background. The result is lighter gray pixels, and not white pixels.

If your only option is still to paint over old pixels, then you'll have to use a slightly bigger radius for the white circle:

var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');

ctx.beginPath();
ctx.arc(50, 50, 40, 0, 2 * Math.PI); // radius of 40
ctx.fill();

ctx.fillStyle = "#FFFFFF";
ctx.strokeStyle = "#FFFFFF";

ctx.beginPath();
ctx.arc(50, 50, 41, 0, 2 * Math.PI); // radius of 41
ctx.fill();
<canvas id="myCanvas" width="150" height="150" style="border: 1px solid #000000;">
</canvas>
<br /> Nothing to see here ;-)

For more on anti-aliasing, see e.g. Can I turn off antialiasing on an HTML <canvas> element?

Peter B
  • 22,460
  • 5
  • 32
  • 69
0

Double buffering in action

Try

step1();

setTimeout(function () {

  step2();

  setTimeout(function () {

    step3();

  }, 1000);
}, 1000);

function step1() {
  clearCanvas('myCanvas1');

  drawShape('myCanvas1'
     ,{type:"circle", strokeStyle:"#000000", fillStyle:"#000000", radious:40, x:50, y:50});
};

function step2() {
  clearCanvas('myCanvas2');

  showOtherCanvas('myCanvas2', 'myCanvas1');
};

function step3() {
  clearCanvas('myCanvas1');

  drawShape('myCanvas1'
     ,{type:"circle", strokeStyle:"#000000", fillStyle:"#000000", radious:40, x:50, y:50});

  showOtherCanvas('myCanvas1', 'myCanvas2');
};

function drawCircle (canvasID, info) {
  var canvas = document.getElementById(canvasID);
  var ctx = canvas.getContext('2d');
  
  ctx.fillStyle=info.fillStyle;
  ctx.strokeStyle=info.strokeStyle;

  ctx.beginPath();
  ctx.arc(info.x, info.y, info.radious, 0, 2 * Math.PI);
  ctx.fill();

  ctx.beginPath();
  ctx.arc(info.x, info.y, info.radious, 0, 2 * Math.PI);
  ctx.stroke();
}

function showOtherCanvas(cnv1, cnv2) {
  var c1 = document.getElementById(cnv1);
  var c2 = document.getElementById(cnv2);
  
  c1.style['z-index'] = 3;
  c2.style['z-index'] = 1;
  c1.style['z-index'] = 2;
}

function clearCanvas(canvasID) {
  var canvas = document.getElementById(canvasID);
  var ctx = canvas.getContext('2d');
  
  ctx.fillStyle="#FFFFFF";
  ctx.strokeStyle="#FFFFFF";
  
  ctx.fillRect(0,0,640,400);
} 



function drawShape (canvasID, info) {
  switch (info.type) {
    case  "circle" : drawCircle(canvasID, info);
  }
}
<canvas id="myCanvas2" width="640" height="400"
 style="border: 1px solid #000000; position: absolute; top: 10; left: 10; z-index:1">
</canvas>
<canvas id="myCanvas1" width="640" height="400"
 style="border: 1px solid #000000; position: absolute; top: 10; left: 10; z-index:2">
</canvas>

The change is so fast you won't see any flicker.

Dominique Fortin
  • 2,212
  • 15
  • 20
  • Im a starter with canvas, what exactly are you doing in this function? – l33t5p34k3r Nov 09 '18 at 16:53
  • 1
    @l33t5p34k3r drawCircle just draws a circle with a border (the border can be of the same color). The Double buffering bit is the interesting part. If you draw a white circle on top of a black circle to hide the black circle, you always see visual artifacts. And since a canvas doesn't remember what you have ask to draw, if you want to erase something, you have to redraw everything and double buffering make the redrawing look instantaneous. Play with it, add new shapes, change the timing, have fun. – Dominique Fortin Nov 09 '18 at 17:06