Remove circle drawn in html5 canvas once user clic

2019-09-16 17:04发布

问题:

I wrote a code that generates randomly 60 circles in a canvas, how do I handle that an event onclick circle pressed disappear and after is generated another? which may be the best solution? the code is:

var canvas, ctx;
var circles = [];
var selectedCircle;
var vel=200;    

function Circle(x, y, radius){
    this.x = x;
    this.y = y;
    this.radius = radius;
}

function clear() { // clear canvas
    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
}

function drawCircle(ctx, x, y, radius) {

    var color = 'rgb(' + (Math.floor(Math.random() * 256)) + ',' + (Math.floor(Math.random() * 256)) + ',' + (Math.floor(Math.random() * 256)) + ')';
    ctx.fillStyle = color;
    ctx.beginPath();
    ctx.arc(x, y, radius, 0, Math.PI*2, true);
    ctx.closePath();
    ctx.fill();
}

function generate(){

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

    var circleRadius = 25;
    var width = canvas.width;
    var height = canvas.height;
    var timer, j = 0;

    var circlesCount = 60;
    for (var i=0; i<circlesCount; i++) {
        var x = Math.random()*width;
        var y = Math.random()*height;    
        circles.push(new Circle(x,y,circleRadius));
    }

    timer = window.setInterval(function()

    {
        if(j==60)
        {
            clear();
            return;
        }
        drawCircle(ctx, circles[j].x, circles[j].y, circles[j].radius);
        // go to next circle
        j++;
    }, vel);
}

回答1:

The best solution for this IMO would be to use svg, which will create SVGElements, each one with it's own events interface.

Now, it's not impossible to do it with a canvas, but as mentioned by @VickyGonsalves, you'll have to store all circles positions, calculate their superficy and check if the click event's clientX and clientY are inside one of them, then redraw the whole without the ones being clicked.

However, the new Path2D interface, allows to store paths and reuse them later, or use them into context's methods such as fill() and isPointInPath().

So here is a simple solution using the Path2d() constructor, which is supported neither by IE, nor by Safari.

var canvas = document.createElement('canvas'),
  ctx = canvas.getContext('2d'),
  circles = [];
document.body.appendChild(canvas);
canvas.width = 500;
canvas.height = 500;

function Circle(x, y, radius) {
  var c = new Path2D();
  c.arc(x, y, radius, 0, Math.PI * 2);
  return c;
}

function init() {
  ctx.strokeStyle = 'white';
  for (var i = 0; i < 60; i++) {
    circles.push(Circle((Math.random() * (canvas.width - 40)) + 20, (Math.random() * (canvas.height - 40)) + 20, 20));
    ctx.fill(circles[i], "nonzero");
    ctx.stroke(circles[i], "nonzero");
  }
}

function clickHandler(e) {
  var r = canvas.getBoundingClientRect(),
    x = e.clientX - r.left,
    y = e.clientY - r.top,
    i;

  for (i = circles.length - 1; i >= 0; --i) {
    console.log(i);
    if (ctx.isPointInPath(circles[i], x, y, 'nonzero')) {
      circles.splice(i, 1);
    }
  }

  ctx.clearRect(0, 0, canvas.width, canvas.height);
  for (i = 0; i < circles.length; i++) {
    ctx.fill(circles[i], "nonzero")
    ctx.stroke(circles[i], "nonzero");
  }
}
canvas.addEventListener('click', clickHandler, false);
init();