Detect mouse clicks on circles on HTML5 canvas

3.9k views Asked by At

I'm new to canvas and I'm trying to listen to mouse clicks on the circles that I previously drew on canvas. I'm trying to change the colour of the circles (maybe to green) when I click on them.

var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');


var radius = 15;
for (var i = 0; i < 600; i += 100) {
  var x = 100 + i;
  var y = 100;
  draw_circle(i, x, y, radius);
}

function draw_circle(ID, x, y, radius) {
  context.beginPath();
  context.arc(x, y, radius, 0, Math.PI * 2, false);
  context.fillStyle = 'red';
  context.fill();
  context.lineWidth = 3;
  context.strokeStyle = 'black';
  context.stroke();
  context.closePath();

}
<!DOCTYPE HTML>
<html>

<head>
  <style>
    html,
    body {
      width: 100%;
      height: 100%;
      margin: 0px;
    }
  </style>
</head>

<body>
  <canvas id="myCanvas" width="700" height="700"></canvas>

</body>

</html>

3

There are 3 answers

0
Amadan On BEST ANSWER

With SVG, it would be easy - a circle is an element, and can have a click handler, and has fill that you can manipulate to change colour.

With Canvas, you need to:

  • save the data for each circle you draw (center and radius)
  • capture click on canvas as cx, cy
  • check every circle data x, y, r you have, see whether dx * dx + dy * dy < r * r, where dx = cx - x, dy = cy - y. Circles that satisfy this equation were clicked
  • repaint the circle
0
Trương Khánh On

With Canvas, you can use function addEventListener. There are quite a few mouse events you can detect: mousedown, mouseup, mousemove, mouseout and mouseover. Here is a example:

<!DOCTYPE HTML>
<html>
<head>
      <style>
            html,
            body {
                 width: 100%;
                 height: 100%;
                 margin: 0px;
            }
      </style>
      <script>
            function initialize() {
                 var canvas = document.getElementById("myCanvas");
                 canvas.addEventListener("mousedown", doMouseDown, false);
            }
            function doMouseDown() {
                 canvas_X = event.pageX;
                 canvas_Y = event.pageY;
                 alert("X = " + canvas_X + "Y = " + canvas_Y);
            }
      </script>
</head>
<body>
     <canvas id="myCanvas" width="700" height="700"></canvas>
</body>
</html>
0
AudioBubble On

Just add the arc path again and use isPointInPath() with the mouse position. Only one arc can be tested at once, but it's fast to clear and add new paths. Do this in a loop.

Example

var c = document.querySelector("canvas"), ctx = c.getContext("2d");

getArc(50, 50, 40);
ctx.fill();

c.onclick = function(e) {
  var rect = this.getBoundingClientRect(),   // get abs. position of canvas
      x = e.clientX - rect.left,             // adjust mouse-position
      y = e.clientY - rect.top;
  
  getArc(50, 50, 40);                        // get path wo/ filling/stroking it
  if (ctx.isPointInPath(x, y)) alert("Clicked");
};

function getArc(x, y, r) {
  ctx.beginPath();
  ctx.arc(x, y, r, 0, Math.PI*2);
  ctx.closePath();
}
<canvas></canvas>

The other approach is to use math and trigonometry:

// at this point we have the mouse position, so:
var dx = x - arcX,
    dy = y - arcY,
    dist = Math.abs(Math.sqrt(dx*dx + dy*dy));

if (dist <= radius) { ...clicked... };

Tip: you can skip squaring the dist by using r2 instead.