Code Rider
Code Rider

Reputation: 2063

How to use multiple click event on a canvas

I have drawn a circle with canvas using following code.

<div class="abc"><canvas id="myCanvas">HTML5 canvas tag.</canvas></div>
<script>

    var c = document.getElementById("myCanvas");
    var ctx = c.getContext("2d");
    ctx.beginPath();
    ctx.arc(100,75,50,-0.1*Math.PI,1.7*Math.PI);
    ctx.lineWidth = 15;
    ctx.strokeStyle = "#c32020";
    ctx.stroke();

    var c2 = document.getElementById("myCanvas");
    var ctx2 = c2.getContext("2d");
    ctx2.beginPath();
    ctx2.arc(100,75,50,1.7*Math.PI,-0.1*Math.PI);
    ctx2.lineWidth = 15;
    ctx2.strokeStyle = "#a9a9a9";
    ctx2.stroke();

</script>

Here is the result on the web browser.

enter image description here

Now I need to call two different javascript function when the user clicks on red part and gray part of the circle.

On click of the red part it should call function1 and on click of gray part, it should call function2.

I've tried a lot but didn't succeed. I need some expert's help to implement it.

Upvotes: 3

Views: 2442

Answers (2)

user1693593
user1693593

Reputation:

Letting the browser do (most of) the work

On click of the red part it should call function1 and on click of gray part, it should call function2.

You can use reusable path objects to store the different paths you want to test against and then use isPointInPath() with path and coordinates as arguments.

By checking each path for a hit you can assign a different call based on for example index.

And there is no need to do this:

var c2 = document.getElementById("myCanvas");
var ctx2 = c2.getContext("2d");

This will simply reference the same context as a canvas can only have one - if requested more than once the same will be given (or null if different type).

How to use multiple click event on a canvas

You can share the click handler to do what you want as shown below -

For modern browsers you can use both Path2D objects to store path information you want to use later (I'll address older browsers in the second example).

Example

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var p1 = new Path2D();
var p2 = new Path2D();
var paths = [p1, p2];   // store paths in array for check later

// store arc parts to respective path objects
p1.arc(100, 75, 50, -0.1 * Math.PI, 1.7 * Math.PI);  // red part
p2.arc(100, 75, 50, 1.7 * Math.PI, -0.1 * Math.PI);  // grey part

// render the two path objects using a common context, but different style
ctx.lineWidth = 15;

ctx.strokeStyle = "#c32020";
ctx.stroke(p1);

ctx.strokeStyle = "#a9a9a9";
ctx.stroke(p2);

// check for clicks on common canvas
c.onclick = function(e) {
  var rect = this.getBoundingClientRect(),  // adjust click coordinates
      x = e.clientX - rect.left,
      y = e.clientY - rect.top;

  // iterate through path array to test each path for hits
  for(var i = 0; i < paths.length; i++) {
    if (ctx.isPointInStroke(paths[i], x, y)) {      // check which path
      console.log("Path " + (i+1) + " clicked");
      break;
    }
  }
};
<canvas id="myCanvas"></canvas>

Browser compatibility

Older browsers however, won't support the isPointInStroke(), such as IE11.

For this scenario you can use simple math to figure out if the click is within the radius of the arcs:

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.lineWidth = 15;
ctx.arc(100, 75, 50, -0.1 * Math.PI, 1.7 * Math.PI);  // red part
ctx.strokeStyle = "#c32020";
ctx.stroke();

ctx.beginPath();
ctx.arc(100, 75, 50, 1.7 * Math.PI, -0.1 * Math.PI);  // grey part
ctx.strokeStyle = "#a9a9a9";
ctx.stroke();

// check for clicks on common canvas
c.onclick = function(e) {
  var rect = this.getBoundingClientRect(),  // adjust click coordinates
      x = e.clientX - rect.left,
      y = e.clientY - rect.top,
      diffX = 100 - x,
      diffY = 75 - y,
      len = diffX*diffX + diffY*diffY,     // we don't need to square-root it:
      r1 = 43*43,         // it's faster to scale up radius (50-50% of linewidth)
      r2 = 57*57;         // radius + 50% of linewidth

  // are we on the edge of the circle?
  if (len >= r1 && len <= r2) {
    // now find angle to see if we're in red or grey area
    var angle = Math.atan2(diffY, diffX);
    if (angle > 0.7 * Math.PI && angle < 0.9 * Math.PI) {
      console.log("Grey part");
    }
    else {
      console.log("Red part");
    }
  }
};
<canvas id="myCanvas"></canvas>

Note that a special case in the latter example, i.e. when the arc crosses the 0/360° point, you will want to split the checks [0, angle> and [angle, 360>.

Upvotes: 3

Anthony McGrath
Anthony McGrath

Reputation: 802

You will need to add a click event to the canvas element and calculate if the red or gray is clicked. Here's some code to get you started, but you'll still have to figure out what coordinates your circle area has.

var elem = document.getElementById('myCanvas'),
elemLeft = elem.offsetLeft,
elemTop = elem.offsetTop;

// Add event listener for `click` events.
elem.addEventListener('click', function(event) {
var x = event.pageX,
    y = event.pageY;

// use x and y to determine if the colored regions are clicked and execute code accordingly

}, false);

Code gotten from here: How do I add a simple onClick event handler to a canvas element?

Upvotes: 0

Related Questions