Search code examples
javascripthtmlcsscanvasmouseclick-event

How to click one circle among others in canvas using JavaScript


I want to click each circle separately from an array of circles. Because I want to do different tasks for each circle after being clicked. Though multiple circles are stored inside the array circles[] when I am clicking on the circles the alert is not showing without one circle and it's showing the alert 5 times. I am assuming that is the last circle which has been drawn randomly and only this circle has the click effect! Can someone please help me to figure this out?

const canvas = document.getElementById('flower');
const ctx = canvas.getContext('2d');
var offsetX = canvas.offsetLeft;
var offsetY = canvas.offsetTop;
var circles = [];

function main(){
    if (typeof document !== 'undefined') {
            var r = 20; 
            for (var j=0; j<5; j++){
                var cx = random()*(canvas.width);
                var cy = random()*(canvas.height);
                var r = 25;
                var color = "rgb(" + Math.floor(random() * 256) + "," + Math.floor(random() * 256)
                            + "," + Math.floor(random() * 256) + ")";
                ctx.beginPath();
                ctx.arc(cx, cy, r, 0, 2 * Math.PI);
                ctx.fillStyle = color;
                ctx.fill();
                ctx.closePath();
                var obj = {}; 
                obj['x'] = cx;
                obj['y'] = cy;
                circles.push(obj);
                
            }
            //console.log(circles); 5 circles are stored in circles[]
            circles.forEach(function(entry){
            canvas.addEventListener('click', function(e) {
                    var clickX = e.clientX - offsetX;
                    var clickY = e.clientY - offsetY;
                    var dx = cx - clickX;
                    var dy = cy - clickY;
                    if (dx * dx + dy * dy <= r * r) {
                        alert("you are inside the circle");
                    }
                });
            });
                                
        }
}



    var seed = 1;
    function random() {
        var x = Math.sin(seed++) * 10000;
        return x - Math.floor(x);
    }

main();
html, body, div {
    width:  100%;
    height: 100%;
    margin: 0;
  }
<body>
    <div id="design">
        <canvas id="flower"></canvas>
    </div>
</body>


Solution

  • To achieve expected result, use below option of using isPointInPath method to detect click of canvas shape

    1. Use Path2D constructor to draw circle

      const circle = new Path2D(); circle.arc(cx, cy, r, 0, 2 * Math.PI); ctx.fillStyle = color; ctx.fill(circle);

    2. Use below click event Listener

    canvas.addEventListener("click", function(event) { if (ctx.isPointInPath(circle, event.clientX, event.clientY)) { alert("you are inside the circle"); } });

    Please refer this link for more details on https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/isPointInPath

    Sample working code for reference

    const canvas = document.getElementById("flower");
    const ctx = canvas.getContext("2d");
    var offsetX = canvas.offsetLeft;
    var offsetY = canvas.offsetTop;
    var circles = [];
    
    function main() {
      if (typeof document !== "undefined") {
        var r = 20;
        for (var j = 0; j < 5; j++) {
          var cx = random() * canvas.width;
          var cy = random() * canvas.height;
          var r = 25;
          var color =
            "rgb(" +
            Math.floor(random() * 256) +
            "," +
            Math.floor(random() * 256) +
            "," +
            Math.floor(random() * 256) +
            ")";
          const circle = new Path2D();
          circle.arc(cx, cy, r, 0, 2 * Math.PI);
          ctx.fillStyle = color;
          ctx.fill(circle);
          canvas.addEventListener("click", function(event) {
            if (ctx.isPointInPath(circle, event.clientX, event.clientY)) {
              alert("you are inside the circle");
            }
          });
        }
      }
    }
    
    var seed = 1;
    function random() {
      var x = Math.sin(seed++) * 10000;
      return x - Math.floor(x);
    }
    
    main();
    html, body, div {
        width:  100%;
        height: 100%;
        margin: 0;
      }
    <body>
        <div id="design">
            <canvas id="flower"></canvas>
        </div>
    </body>

    Codepen - https://codepen.io/nagasai/pen/NWWNmdj