Events attached to object inside canvas

前端 未结 3 705

I have simply canvas code which draw rect on the canvas

var x=document.getElementById(\"canvas\");
var ctx=x.getContext(\"2d\");
ctx.rect(20,20,150,100);
ctx         


        
3条回答
  •  萌比男神i
    2021-01-06 07:11

    Regions

    Depending on how well you want to support various and older browsers, there is addHitRegion() that you can use by enabling it through flags in Firefox and Chrome (at the moment of this being written):

    Firefox: about:config -> search "hitregions" and set to true
    Chrome: chrome://flags/ -> Enable experimental canvas features

    This is the only technique that integrates directly with the event system. I would not recommend it for production quite yet though, and AFAIK there is not a polyfill for it either - but to show how easy it is to use:

    var x=document.getElementById("canvas");
    var ctx=x.getContext("2d");
    ctx.rect(20,20,150,100);
    ctx.addHitRegion({id: "demo"});   // enable in flags in Chrome/Firefox
    ctx.stroke();
    
    x.addEventListener("click", function(e) {
      if (e.region && e.region === "demo") alert("Hit!");
    })

    Path: isPointInPath

    The other techniques require one to manually implement a mechanism for hit-detection. One is by using isPointInPath(). You simply rebuild the paths you want to test, one by one, then run your (adjusted) x/y mouse coordinate against it:

    var x=document.getElementById("canvas");
    var ctx=x.getContext("2d");
    generatePath();
    ctx.stroke();
    
    x.addEventListener("click", function(e) {
      var r = this.getBoundingClientRect(),
          x = e.clientX - r.left,
          y = e.clientY - r.top;
      
      // normally you would loop through your paths:
      generatePath();
      if (ctx.isPointInPath(x, y)) alert("Hit!");
    })
    
    function generatePath() {
      ctx.beginPath();          // reset path
      ctx.rect(20,20,150,100);  // add region to draw/test
    }

    Path: Path2D objects

    For the latter example there is also the new Path2D objects which can hold a path on their own - the advantage here is that you don't need to rebuild the paths, just pass in the path object with x/y to the isPointInPath() method.

    The problem is that Path2D is not supported in all browsers yet, but there is this polyfill that will fix that for you,

    var x=document.getElementById("canvas");
    var ctx=x.getContext("2d");
    
    var path1 = new Path2D();
    path1.rect(20,20,150,100);  // add rect to path object
    
    ctx.stroke(path1);
    
    x.addEventListener("click", function(e) {
      var r = this.getBoundingClientRect(),
          x = e.clientX - r.left,
          y = e.clientY - r.top;
      
      // normally you would loop through your paths objects:
      if (ctx.isPointInPath(path1, x, y)) alert("Hit!");
    })

    Manually check boundary

    And of course, there is the old technique of using manual boundary checks. This will work in all browsers. Here the advisable thing to do is to create objects that holds the bounds and can also be used to render it. This typically limits you to rectangular areas - more complex shapes will require more complex algorithms (such as the isPointInPath() embeds).

    var x=document.getElementById("canvas");
    var ctx=x.getContext("2d");
    ctx.rect(20,20,150,100);
    ctx.stroke();
    
    x.addEventListener("click", function(e) {
      var r = this.getBoundingClientRect(),
          x = e.clientX - r.left,
          y = e.clientY - r.top;
      
      // normally you would loop through your region objects:
      if (x >= 20 && x < 20+150 && y >= 20 && y < 20+100) alert("Hit!");
    })

提交回复
热议问题