Deleting only the clicked element, not the other elements on the canvas

i am new to coding. Currently creating a game for a school project.

In short, random circles or "targets" will pop up on the screen, and the user has to click them. I tried to make something that would create a new canvas without the clicked circle, but instead it creates an empty canvas and the loop goes again. How do i keep the "un-clicked" circles on my new canvas?

I am sorry if that made no sense :D. If you have any tips, i would appreciate if you could dumb it down for me :D. Any help would be greatly appreciated.

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var radiustracker = [];
var xpos = [];
var ypos = [];
var radius;
var x;
var y;
var color = 'blue';
ctx.fillStyle = 'lightblue';
ctx.fillRect(0, 0, canvas.width, canvas.height);

function randomize() {
  radius = Math.floor(Math.random() * 25) + 10;
  x = Math.floor(Math.random() * 600) + 50;
  y = Math.floor(Math.random() * 400) + 50;
  radiustracker.push(radius);
  xpos.push(x);
  ypos.push(y);
  drawCircle(x, y, radius);
}

function drawCircle(x, y, radius) {
  ctx.beginPath();
  ctx.arc(x, y, radius, 0, 2 * Math.PI);
  ctx.closePath();
  ctx.fillStyle = color;
  ctx.fill();
}

function clickCircle(xmus, ymus) {
  for (var i = 0; i < xpos.length; i++) {
    var distance =
      Math.sqrt(
        ((xmus - xpos[i]) * (xmus - xpos[i])) +
        ((ymus - ypos[i]) * (ymus - ypos[i]))
      );
    console.log(distance);
    if (distance < radiustracker[i]) {
      radiustracker[i] = 0;
      ctx.fillStyle = 'lightblue';
      ctx.fillRect(0, 0, canvas.width, canvas.height);
    }
  }
}

var intervall = setInterval(randomize, 1000);
canvas.addEventListener('click', (event) => {
  const rect = canvas.getBoundingClientRect();
  const x = event.clientX - rect.left;
  const y = event.clientY - rect.top;
  clickCircle(x, y);
});
#canvas {
  display:inline;
  margins:auto;
}
<body>
<canvas id="canvas" height="500" width="700" ></canvas>
</body>

31 thoughts on “Deleting only the clicked element, not the other elements on the canvas”

  1. Instead of having three separate arrays that track the circle x, y, and r, I would use an array of objects like so:

    var circlesDrawn = [];
    //And then the following repeated for each circle you draw
    circlesDrawn.push({
        x: x,
        y: y,
        r: r
    });
    

    At least that way your data is grouped together and has some meaning.

    Secondly, what you want to do, if I understand the question correctly, is to remove a circle that is clicked on. In a JS Canvas you cannot remove something that is drawn, you can only clearRect, so we should use that to our advantage since it’s a faster method anyways than trying to paint over your circle with another clear circle

    My idea was to first clear the canvas, and then draw whatever circles you have in your circles array, and then when the user clicks you can do the same thing expect remove the circle that was clicked from your circles array (you can filter out the element that matches x, y, and r)

    In addition to all this you can also have your interval drawing in a new circle

    var canvas = document.getElementById('canvas');
    var ctx = canvas.getContext('2d');
    
    var circles = [];
    function drawCanvas() {
        ctx.fillStyle = 'lightblue';
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        for (var a = 0; a < circles.length; a++) {
            drawCircle(circles[a].x, circles[a].y, circles[a].r);
        }
    }
    function drawCircle(x, y, radius){
        ctx.beginPath();
        ctx.arc(x, y, radius, 0, 2 * Math.PI);
        ctx.closePath();
        ctx.fillStyle = color;
        ctx.fill();
    }
    function clickCircle(xmus, ymus){
        for (var i = 0; i < circles.length; i++) {            
            var distance = Math.sqrt(
                Math.pow(xmus - circles[i].x, 2)
                + 
                Math.pow(ymus - circles[i].y, 2)
            );
           console.log(distance);
           if(distance < circles[i].r){   
               //Remove the circle from our array
                circles.splice(i, 1); //This removes 1 element from our circles array at index i
               //Then redraw our canvas from the beginning
               drawCanvas();
            }
        }
    }
    
    canvas.addEventListener('click', (event) => {
        const rect = canvas.getBoundingClientRect();
        const x = event.clientX - rect.left;
        const y = event.clientY - rect.top;
        clickCircle(x,y);
    });
    
    function randomize(){
        var radius = Math.floor(Math.random()*25)+10;
        var x = Math.floor(Math.random()*600)+50;
        var y = Math.floor(Math.random()*400)+50;
        circles.push({
            x: x,
            y: y,
            r: radius
        });
        drawCircle(x,y,radius);
    }
    
    var interval = setInterval(randomize, 1000);
    

    I did you the favor of cleaning up some of your code and what not

    The way it works is you need to call drawCanvas once on its own, and since you have 0 circles to start with, it’ll draw all 0 circles and set up your canvas. Then you register what will happen when you click on a circle, and then you set the interval to start drawing a new circle every second, hopefully that works and isn’t too complicated. I tested it out and it works perfectly for me!

    Reply

Leave a Comment