Canvas isPointInPath () with multiple paths

I have a canvas "object" named Box and I need to detect when the mouse is over it.

I have a draw () method for this object, which I use the isPointInPath () method, but only change when the cursor is on the last path. Any suggestions?

Box.prototype.draw = function() {

    this.ctx.beginPath();
    this.ctx.moveTo(this.matrix.p1.x, this.matrix.p1.y);
    this.ctx.lineTo(this.matrix.p2.x, this.matrix.p2.y);
    this.ctx.lineTo(this.matrix.p3.x, this.matrix.p3.y);
    this.ctx.lineTo(this.matrix.p4.x, this.matrix.p4.y);
    this.ctx.lineTo(this.matrix.p1.x, this.matrix.p1.y);
    this.ctx.closePath();

    this.ctx.fillStyle = 'rgba(255, 255, 255, 0.1)';
    this.ctx.fill();

    if (this.ctx.isPointInPath(mouse.x, mouse.y)) {
        this.canvas.style.cursor = 'pointer';
        this.ctx.fillStyle = 'rgba(0, 0, 255, 0.5)';
        this.ctx.fill();
        return;
    }

    this.canvas.style.cursor = 'default';

};

      

+3


source to share


2 answers


context.isPointInPath

only checks the last defined path (from the last context.beginPath).

So, you should individually test each of your form paths:

  • "Override" the shape of the first shape. Override means re-issuing the commands of the first shape of the path, but you don't have to actually press () or fill () on the first shape.

  • Check if the mouse is inside the first shape using isPointInPath.

  • Continue testing the second, third, ... last form.



By the way, if all of your shapes are rectangles, you can use math to check if the mouse is inside any rectangle:

var isInside=(
    mouseX>=RectX && 
    mouseX<=RectX+RectWidth &&
    mouseY>=RectY &&
    mouseY<=RectY+RectHeight
);

      

+5


source


You can store each path in an array or object for later access.

In general, you need to create Path2D

. (check browser support before use).



Here's a really simple grid of hexagons to demonstrate this: http://codepen.io/pixelass/pen/37445407893ef783e414ce136af5633a

const C = document.createElement('canvas');
const $ = C.getContext('2d');

const rows = 5;
const cols = 5;
var side = 50;
C.width = cols * side * Math.sqrt(3);
C.height = rows * 1.5 * side;

const paths = [];

var dy = -1;
for (let i = 0; i < (rows + 1) * (cols + 1); i++) {
  let dx = i % (cols + 1);
  dy += dx ? 0 : 1;
  dx += dy % 2 ? -.5 : 0;
  let cx = dx * (side * Math.sqrt(3)) + side / 2 * Math.sqrt(3);
  let cy = (dy - .5) * (side * 1.5) + side;
  let path = new Path2D();
  for (let j = 0; j < 6; j++) {
    let x = Math.cos(Math.PI / 3 * j + Math.PI / 6) * side + cx;
    let y = Math.sin(Math.PI / 3 * j + Math.PI / 6) * side + cy;
    if (j) {
      path.lineTo(x, y);
    } else {
      path.moveTo(x, y);
    }
  }
  path.closePath();
  $.fillStyle = `hsl(${10*i},50%,50%)`;
  $.fill(path);
  paths.push(path);
}

C.addEventListener('mousemove', e => {
  let bound = C.getBoundingClientRect();
  let x = e.pageX - bound.top;
  let y = e.pageY - bound.left;
  paths.forEach((path, index) => {
    if ($.isPointInPath(path, x, y)) {
      console.log(index);
    }
  });
});

document.body.appendChild(C);

      

+3


source







All Articles