【问题标题】:How to use multiple click event on a canvas如何在画布上使用多次点击事件
【发布时间】:2018-02-10 02:52:51
【问题描述】:

我使用以下代码用canvas 画了一个圆圈。

<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>

这是网络浏览器上的结果。

现在当用户点击圆圈的红色部分和灰色部分时,我需要调用两个不同的javascriptfunction

在红色部分的click 上,它应该调用function1,在点击灰色部分时,它应该调用function2

我尝试了很多,但没有成功。我需要一些专家的帮助来实施它。

【问题讨论】:

    标签: javascript jquery html canvas html5-canvas


    【解决方案1】:

    让浏览器完成(大部分)工作

    点击红色部分调用function1,点击灰色部分调用function2。

    您可以使用可重用的路径对象来存储要测试的不同路径,然后使用isPointInPath() 将路径和坐标作为参数。

    通过检查每个路径是否有命中,您可以根据例如索引分配不同的调用。

    而且没有必要这样做:

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

    这将简单地引用相同的上下文,因为画布只能有一个 - 如果多次请求,将给出相同的内容(如果类型不同,则为 null)。

    如何在画布上使用多次点击事件

    您可以共享点击处理程序来做您想做的事情,如下所示 -

    对于现代浏览器,您可以同时使用 Path2D 对象来存储您以后要使用的路径信息(我将在第二个示例中介绍较旧的浏览器)。

    示例

    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;
        }
      }
    };
    &lt;canvas id="myCanvas"&gt;&lt;/canvas&gt;

    浏览器兼容性

    但是,较旧的浏览器不支持isPointInStroke(),例如 IE11。

    对于这种情况,您可以使用简单的数学计算来确定点击是否在圆弧的半径内:

    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");
        }
      }
    };
    &lt;canvas id="myCanvas"&gt;&lt;/canvas&gt;

    请注意后一个示例中的特殊情况,即当圆弧穿过 0/360° 点时,您需要拆分检查 [0, angle> 和 [angle, 360>。

    【讨论】:

    • 酷。这行得通。您能告诉我您是如何在点击事件中使用 100、75、43、57、0.7 和 0.9 等值的吗?将来我可能需要使这个圆圈变小或变大,然后我也需要更改这些值。所以你能指导我你是如何计算这些值的,以便我将来可以根据需要更改这些值。
    • @CodeRider 这些是您用来绘制圆的值(x/y 中心、内线半径、外线半径(线宽)、起始角度和结束角度)。 :) 您可以而不是像在示例中那样对它们进行硬编码,而是为它们使用变量,或者代表一个圆圈的小对象等。
    【解决方案2】:

    您需要向画布元素添加一个点击事件,并计算是否点击了红色或灰色。 这里有一些代码可以帮助您入门,但您仍然需要弄清楚您的圆圈区域的坐标。

    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);
    

    从这里获取的代码:How do I add a simple onClick event handler to a canvas element?

    【讨论】:

      猜你喜欢
      • 2012-04-11
      • 1970-01-01
      • 2011-03-05
      • 1970-01-01
      • 2012-08-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多