Canvas event handling, listening for clicks

Keywords: Programming JQuery html5 Javascript

DOM is a very important part of the Web front-end domain. It is not only used in dealing with HTML elements, but also in graphic programming. For example, SVG drawing, all kinds of graphics are inserted into the page in the form of DOM nodes, which means that the DOM method can be used to manipulate graphics. For example, there is an element that can directly add click events $(' p1'). click(function(){with jquery. }. However, this DOM processing method is no longer applicable in HTML5 Canvas. Canvas uses another set of mechanisms. No matter how many graphics are drawn on Canvas, Canvas is a whole. Graphics themselves are actually part of Canvas and can not be obtained separately, so it is impossible to add JavaScript events directly to a graph.

Bind events to Canvas elements:
Since events can only reach the level of Canvas elements, if you want to go further and identify which graphics clicks occur inside Canvas, you need to add code to process them. The basic idea is to bind events to Canvas elements. When an event occurs, check the location of the event object, and then check which graphics cover the location. For example, draw a rectangle that covers the range of x-axis 10-110 and y-axis 10-110. As long as the mouse clicks in this range, it can be regarded as clicking on the rectangle, which can manually trigger the click events that the rectangle needs to handle. In fact, the idea is relatively simple, but the implementation is still a little complicated. Not only should we consider the efficiency of this judgment process, but in some places we need to redefine the event type and redefine a capture and bubbling mechanism within Canvas.


html:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
</head>
    <body>
        <canvas id="myCanvas" width="320" height="620" style="position: absolute;top: 100px;left: 100px;background: burlywood;"></canvas>
    </body>
</html>

js:

arr = [
 {x:0, y:0, width:320, height:200,content:'I'm the first box.',color:'green'},
  {x:0, y:204, width:320, height:200,content:'I'm the second box.',color:'blue'},
  {x:0, y:404, width:320, height:200,content:'I'm the third box.',color:'yellow'}
];
cvs = document.getElementById('myCanvas');
ctx = cvs.getContext('2d');
draw();

//Monitor events
cvs.addEventListener('click', function(e){
  p = getEventPosition(e);
  //Judge which rectangle you clicked
  if(p.y <= arr[0].height){
    console.log('You clicked on the first rectangle',p)
  }
  if(p.y>arr[0].height && p.y <= (arr[1].height+arr[1].y)){
    console.log('You clicked on the second rectangle',p)
  }
  if(p.y>(arr[1].height+arr[1].y) && p.y <= (arr[2].height+arr[2].y)){
    console.log('You clicked on the third rectangle',p)
  }
}, false);

//Note: To use this function, you need to set the position of the Canvas element to absolute.
//To determine the location of the event object, the layerX and layerY attributes of the event object e represent the coordinates in the internal coordinate system of Canvas.
function getEventPosition(ev){
  var x, y;
  if (ev.layerX || ev.layerX == 0) {
    x = ev.layerX;
    y = ev.layerY;
  } else if (ev.offsetX || ev.offsetX == 0) { // Opera
    x = ev.offsetX;
    y = ev.offsetY;
  }
  return {x: x, y: y};
}

//Drawing images
    function draw(p){
  var who = [];
  ctx.clearRect(0, 0, cvs.width, cvs.height);
  arr.forEach(function(v, i){
    ctx.beginPath();
    ctx.rect(v.x, v.y, v.width, v.height);
    ctx.font="20px Georgia";
    ctx.fillStyle=v.color;
    ctx.fillText(v.content,0,v.y+20);
    ctx.stroke();
    if(p && ctx.isPointInPath(p.x, p.y)){
      //If event coordinates are passed in, use isPointInPath to determine
      //If the current environment covers that coordinate, put the index value of the current environment in the array.
      who.push(i);
    }
  });
  //According to the index value in the array, the corresponding elements can be found in the arr array.
  return who;
}

Reference address

Posted by Kieran Huggins on Tue, 14 May 2019 09:52:17 -0700