Ad

Canvas Clearing Cards

- 1 answer


When I click on a card element, I want it to clear the canvas and redraw everything except for the card that was clicked on.

The problem is, clicks on some positions clear more than one card, and i I don't know how to fix it. I have been trying to fix it but so far haven't been successful.

let elem = document.getElementById("canvas"),
ctx = elem.getContext("2d"),
elemLeft = elem.offsetLeft,
elemTop = elem.offsetTop;
let drawHelper = {
   pintarImagenes: function() {
         imagenes.forEach(function(image){
           drawHelper.pintarImagen(image);
         });
   },
   pintarImagen: function(image) {
     ctx.save();
     ctx.drawImage(image.image, image.x, image.y);
     ctx.clip();
     ctx.restore();
   }
};
let distancias =[30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330, 360, 390, 410, 440, 470, 510, 540, 570, 600, 630, 660, 690, 720, 750, 780, 810, 840, 870, 900];
let imagenes = [];
for ( let i = 0; i < 22; i++) {
  imagenes.push({
    x: (30*i),
    x1:((30*i)+270),
    y: 20,
    y1: 545,
    image: new Image()
  });
  imagenes[i].image.src = 'image.png';
  imagenes[i].image.onload = drawHelper.pintarImagenes;
}
elem.addEventListener('click', function onClickCanvas(event){
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.beginPath();
      let i = 0;
      let newImagesArray = [];
      imagenes.forEach(function(image = distancias[i]){
        if( image.x <= event.clientX
          && image.y <= event.clientY
          && image.x1 >= event.clientX
          && image.y1 >= event.clientY){
            console.log(i);
          } else {
            newImagesArray.push(image);
          }
          i++;
        });
        imagenes = newImagesArray;
        drawHelper.pintarImagenes();
      });

Codepen: https://codepen.io/Raya082/pen/XWbpGKY

Ad

Answer

A few issues:

  • The image width is larger than 270, so change x1:((30*i)+270) to x1:((30*i)+340)

  • The cursor position given by clientX and clientY is not relative to the canvas element, so use event.clientX - elem.offsetLeft and event.clientY - elem.offsetTop to get to the right x, y coordinates.

  • As you have overlapping cards, your condition will often match more than one card. In reality you only want to match the rightmost of those candidates, since the overlapping happens from left to right, which is also the order of the imagenes array. As you only need at the most one match, you can better use findIndex instead of forEach: find the first card that comes after the cursor's X-coordinate, and remove the card that precedes that card.

Here is the corrected code for dealing with the latter two points:

elem.addEventListener('click', function onClickCanvas(event){
    let x = event.clientX - elem.offsetLeft;
    let y = event.clientY - elem.offsetTop;
    let i = imagenes.findIndex(image => image.x > event.clientX);
    if (i == -1) i = imagenes.length;
    i--;
    if (i >= 0) {
        let image = imagenes[i];
        if (image.x <= x && image.y <= y && image.x1 >= x && image.y1 >= y) {
           imagenes.splice(i, 1);
        }
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.beginPath();
        drawHelper.pintarImagenes();
    }
});
Ad
source: stackoverflow.com
Ad