Нажатие формы холста удаляет более одной фигуры - PullRequest
0 голосов
/ 12 марта 2019

Я пытаюсь определить щелчок холста, и если координаты щелчка соответствуют форме.Это работает нормально, проблема в том, что когда фигуры перекрываются на холсте (одна фигура может быть меньше другой), тогда обе фигуры удаляются.Есть ли способ избежать этого и удалить только по одному за раз?

 addShape() {
    const randomNum = (min, max) => Math.round(Math.random() * (max - min) + min),
          randomRad = randomNum(10, 100),
          randomX = randomNum(randomRad, this.canvas.width - randomRad);

    let shape = new Shape(randomX, randomNum, randomRad);

    shape.drawShape();
    this.shapes.push(shape);
  }

canvasClick() {
    if(!this.paused) {
      const canvasRect = event.target.getBoundingClientRect(),
            clickedX = event.clientX - canvasRect.left,
            clickedY = event.clientY - canvasRect.top;

      for (let i = 0; i < this.shapes.length; i++) {

        if(Math.pow(clickedX - this.shapes[i].x, 2) + Math.pow(clickedY - this.shapes[i].y, 2) 
           < Math.pow(this.shapes[i].rad,2)) {

          this.shapes.splice(i, 1);
        }
      }
    }
  }

Заранее спасибо за помощь!

Ответы [ 2 ]

0 голосов
/ 12 марта 2019

Если я понял, что вы, то решение довольно простое. Просто break цикл после удаления одной фигуры. Как то так:

for (let i = 0; i < this.shapes.length; i++) {
    if (
        Math.pow(clickedX - this.shapes[i].x, 2)
        + Math.pow(clickedY - this.shapes[i].y, 2)
        < Math.pow(this.shapes[i].rad, 2)
    ) {
        this.shapes.splice(i, 1);
        break; // <--
    }
}

Вам также может понадобиться сохранить положение z фигур, чтобы вы могли сначала отсортировать их по z, а затем запустить этот цикл, чтобы не удалять фигуру ниже щелкаемой формы.

0 голосов
/ 12 марта 2019

Вот как бы я это сделал.Пожалуйста, прочитайте комментарии в коде.Я использую метод ctx.isPointInPath, но вы можете использовать формулу, если хотите.

Основная идея - выйти из цикла после нахождения и удаления первого круга.Надеюсь, это поможет.

let ctx = canvas.getContext("2d");
canvas.width = 300;
canvas.height = 300;
ctx.fillStyle = "rgba(0,0,0,.5)";
// the array of the circles
let circles = []

class Circle{
  
constructor(){
  this.x = ~~(Math.random() * canvas.width);
  this.y = ~~(Math.random() * canvas.height); 
  this.r = ~~(Math.random() * (40 - 10 + 1) + 10); 
  
  this.draw();
}
draw(){
  ctx.beginPath();
  ctx.arc(this.x,this.y, this.r, 0,2*Math.PI) 
}
}

// create 20 circles
for(i=0;i<20;i++){
let c = new Circle();
ctx.fill()
circles.push(c)    
}

canvas.addEventListener("click",(e)=>{
  // detect the position of the mouse
  let m = oMousePos(canvas, e)
  for(let i=0;i<circles.length;i++){
  // draw a circle but do not fill
  circles[i].draw();
    // check if the point is in path
    if(ctx.isPointInPath(m.x,m.y)){
      //remove the circle from the array
      circles.splice(i, 1);
      // clear the context
      ctx.clearRect(0,0,canvas.width,canvas.height)
      // redraw all the circles from the array
      for(let j=0;j<circles.length;j++){
      circles[j].draw();
      ctx.fill()
      }
      //exit the loop
      return;
    }
  }
})


// a function to detect the mouse position
function oMousePos(canvas, evt) {
  var ClientRect = canvas.getBoundingClientRect();
	return { //objeto
	x: Math.round(evt.clientX - ClientRect.left),
	y: Math.round(evt.clientY - ClientRect.top)
}
}
canvas{border:1px solid}
<canvas id="canvas"></canvas>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...