M00
M00

Reputation: 347

How to find out which part of the circle was clicked, using HTML5 canvas?

I am trying to create Simon game using HTML5 canvas and vanilla JavaScript. I am confused about the coordinate system in the arc() method. I have divided the circle into 4 quadrants and would like to alert the number of the quadrant clicked. But, I am not sure how to find out which part of the circle was clicked. https://jsfiddle.net/xawpLdys/1/

var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var x = canvas.width / 2;
var y = canvas.height / 2;

var pads = [];

var angle = 2 * Math.PI / 4;
var color = ["green","red","blue","yellow"];
var Pads = function(x, y, radius, start, end) {
   this.x = x;
   this.y = y;
   this.radius = radius;
   this.start = start;
   this.end = end;

};
function drawSimon(radius) {
for (var i = 0; i < 4; i++) {
    context.beginPath();
    context.moveTo(x, y);
    context.arc(x, y, radius, i*angle, (i+1)*angle, false);
    context.lineWidth = radius;
    context.fillStyle = color[i];
    context.fill();
    context.lineWidth = 2;
    context.strokeStyle = '#444';
    context.stroke();
    var pad = new Pads(x, y, radius, i*angle, (i+1)*angle);
    pads.push(pad);
}

}

 drawSimon(150);

  $('#myCanvas').click(function (e) {

  /*for (var i = 0; i < pads.length; i++) {
    if (//condition matches) {
        alert (i);
    }
   }*/
  });

Upvotes: 2

Views: 1304

Answers (2)

Md. Khairul Hasan
Md. Khairul Hasan

Reputation: 714

Try This

This example just translates the clicked e.pageX and e.pageY to normal quadrant system. And after some condition, you can determine which part has been clicked.

    $('#myCanvas').click(function (e) {
    var nx,ny;
    nx=-(x- e.pageX);
    ny=y- e.pageY;
        if (nx>0 && ny>0){
      alert('Yellow');
      }else if (nx<0 && ny>0){
      alert('Blue');
      }else if (nx>0 && ny<0){
      alert('Green');
      }else if (nx<0 && ny<0){
      alert('Red');
      }
      
    });

Here is the fiddle https://jsfiddle.net/xawpLdys/3/

UPDATE

John S was right, (It counts clicks that are outside the circle). To prevent the clicks outside the circle from considering, we need to just find the distance from the center of the circle and the clicked point. Then compare the distance with the circle's radius to see it is inside radius.

The updated code :

    $('#myCanvas').click(function (e) {
    var nx,ny;
    nx=-(x- e.pageX);
    ny=y- e.pageY;
     var dx = Math.abs(Math.abs(x)-Math.abs(e.pageX));
     var dy = Math.abs(Math.abs(y)-Math.abs(e.pageY));
     var distance_clicked = Math.sqrt((dx*dx)+(dy*dy));
     if(distance_clicked <= radius){
        if (nx>0 && ny>0){
          alert('Yellow');
          }else if (nx<0 && ny>0){
          alert('Blue');
          }else if (nx>0 && ny<0){
          alert('Green');
          }else if (nx<0 && ny<0){
          alert('Red');
          }
    }
    });

Here is the updated fiddle https://jsfiddle.net/xawpLdys/8/

It still have the limitations of dividing the circle more than 4 slices.

Upvotes: 2

John S
John S

Reputation: 21482

The accepted answer seems a bit limited. It counts clicks that are outside the circle. That could be fixed fairly easily, but it would still be limited to four sections.

To determine if a point is in a sector:

  1. First check if it is within the circle. The Pythagorean theorem comes into play here. Square the x and y values, if their sum is less than or equal to the radius squared, the point is in the circle.
  2. If the point is in the circle, then check if its angle is between the start and end angles for the sector. You can get the point's angle using the arc tangent function from trigonometry.

Try this jsfiddle.

Here are the types that help make this work:

var Circle = function(center, radius) {
    this.center = center;
    this.radius = radius;

    this._radiusSquared = Math.pow(this.radius, 2);
}

$.extend(Circle.prototype, {
    containsPoint: function(point) {
        var relPoint = this.pointToRelPoint(point);
        return Math.pow(relPoint.x, 2) + Math.pow(relPoint.y, 2)
                <= this._radiusSquared;
    },

    getAngleForPoint: function(point) {
        var relPoint = this.pointToRelPoint(point);
        return Math.atan2(-relPoint.y, -relPoint.x) + Math.PI;
    },

    pointToRelPoint: function(point) {
        return { x: point.x - this.center.x, y: point.y - this.center.y }
    }
});

var CircleSector = function(startAngle, endAngle) {
    this.startAngle = startAngle;
    this.endAngle = endAngle;
};

$.extend(CircleSector.prototype, {
    containsAngle: function(angle) {
        return (angle >= this.startAngle) && (angle < this.endAngle);
     },

    containsPoint: function(circle, point) {
        return circle.containsPoint(point)
                && this.containsAngle(circle.getAngleForPoint(point));
    }
});

Upvotes: 2

Related Questions