How to detect click on shape on canvas

by bc_rikko

HTML

<main id="app"></main>

CSS

body {
  background-color: #333;
}

main {
  display: flex;
  justify-content: center;
  align-items: center;
}

JavaScript

class BaseObject {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }

  // 初期表示
  draw(ctx) {}
  // クリック判定
  testHit(point) {}
  // クリックされたときの処理
  clicked(ctx) {}
}

class Box extends BaseObject {
  constructor(x, y, w, h) {
    super(x, y);
    this.w = w;
    this.h = h;
  }

  draw(ctx) {
    ctx.save();
    ctx.fillStyle = "black";
    ctx.fillRect(this.x, this.y, this.w, this.h);
    ctx.restore();
  }

  clicked(ctx) {
    ctx.save();
    ctx.clearRect(this.x, this.y, this.w, this.h);
    ctx.fillStyle = "red";
    ctx.fillRect(this.x, this.y, this.w, this.h);
    ctx.restore();
  }

  testHit(point) {
    return (this.x <= point.x && point.x <= this.x + this.w) &&
           (this.y <= point.y && point.y <= this.y + this.h);
  }
}

class Circle extends BaseObject {
  constructor(x, y, r) {
    super(x, y);
    this.r = r;
  }

  draw(ctx) {
    ctx.save();
    ctx.beginPath();
    ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2, true);
    ctx.fillStyle = "black";
    ctx.fill();
    ctx.restore();
  }

  clicked(ctx) {
    ctx.save();
    ctx.beginPath();
    ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2, true);
    ctx.fillStyle = "red";
    ctx.fill();
    ctx.restore();
  }

  testHit(point) {
    return Math.pow(this.x - point.x, 2) + Math.pow(this.y - point.y, 2) <= Math.pow(this.r, 2);
  }
}

const main = () => {
  const canvas = document.createElement("canvas");
  document.getElementById("app").appendChild(canvas);

  canvas.width = 640;
  canvas.height = 480;

  const ctx = canvas.getContext("2d");
  ctx.save();
  ctx.fillStyle = "white";
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  ctx.restore();

  const items = [];

  const getPos = (min, max) => {
    return Math.round(Math.random() * (max + 1 - min) + min);
  };

  [...Array(5)].forEach((_, i) => {
    const x = getPos(0, canvas.width - 50);
    const y = getPos(0, canvas.height - 50);

    const box = new Box(x, y, 50, 50);
    items.push(box);
  });

 ...