javascript - 识别圆弧上的事件

标签 javascript html canvas automatic-ref-counting mouseevent

我是 html5 的新用户,正在使用 canvas 为我的一个应用程序绘制圆圈。我画了几条弧线来形成一个圆。效果很好。然而我的问题是我想为每个弧关联一个单独的鼠标事件。

我仔细一看,发现 KinteticJS 可能有用。我想知道是否有其他方法可以用于为我使用 Canvas 创建的每个弧附加鼠标事件。请注意,我只使用了一张 Canvas ,没有幽灵 Canvas ,而且我不想使用 SVG。下面是我使用的代码行:

context.arc(x, y, radius, startAngle, endAngle, counterClockwise);
canvas.addEventListener("mousedown", doMouseDown(evt), false);

问候 纳德

最佳答案

简单的回答是:不,但是......

否:

Canvas 不会“记住”在其自身上绘制的任何内容——绘图只是添加到 Canvas 上的颜色像素。 Canvas 不知道弧线的位置,因此无法进行 HitTest 来查看鼠标按下是否位于该弧线内。

但是...你可以使用数学

您可以使用数学来测试任何点是否在圆内。

如果任何 x/y 位于圆的外半径内且不在内半径内,则 x/y 位于圆弧内。

给定centerX,centerY,outerRadius,innerRadius:

测试 x,y 是否在外半径内:

var dx=testX-centerX;
var dy=testY-centerY;
var isInsideOuterRadius=(dx*dx+dy*dy<outerRadius*outerRadius);

测试 x,y 是否不在内半径内:

var isInsideInnerRadius=(dx*dx+dy*dy<innerRadius*innerRadius);

所以 if( isInsideOuterRadius && !isInsideInnerRadius){ alert("x/y 在你的弧内"); }

如果你想变得更奇特:

如果您“记住” Canvas 的弧线,那么 Canvas 会对该弧线进行 HitTest 。

Context.isPointInStroke 将测试 X/Y 是否位于最近绘制的路径内。如果最近的路径是您的弧线,您可以对您的弧线进行 HitTest 。

例如,如果您绘制此弧线:

context.beginPath();
context.arc(100,100,50,0,Math.PI);

您可以通过提供 isPointInStroke 和鼠标坐标来 HitTest 该弧:

if(context.isPointInStroke(mouseX,mouseY)){
    console.log("The mouse is INSIDE the arc");
}else{
    console.log("The mouse is OUTSIDE the arc");
}

要测试多个弧,

  1. 定义一条弧(执行 context.arc 而不执行 context.lines )
  2. 使用 isPointInStroke 测试弧线
  3. 对下一个弧执行#1

IE 除外:(

isPointInStroke 可在 Chrome 和 Firefox 中使用,但尚无法在 Internet Explorer 中使用。

IE 的替代方案:

您可以在圆弧外部定义一条路径,然后使用 isPointInPath 来测试鼠标是否位于该路径内。

[更新:和示例]

enter image description here

这是一个 fiddle (必须使用 Chrome 或 FF 查看 - IE 不起作用):

http://jsfiddle.net/m1erickson/DsPL7/

这里是示例代码:

<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>

<style>
    body{ background-color: ivory; }
    #canvas{border:1px solid red;}
</style>

<script>
$(function(){

    var canvas=document.getElementById("canvas");
    var context=canvas.getContext("2d");
    context.lineWidth=15;

    var canvasOffset=$("#canvas").offset();
    var offsetX=canvasOffset.left;
    var offsetY=canvasOffset.top;

    var PI2=Math.PI*2;

    // create some test data objects
    var arcs=[];

    //outer arcs
    arcs.push({cx:100, cy:100, radius:75, start:0, end: PI2*.33, color:"red"});
    arcs.push({cx:100, cy:100, radius:75, start:PI2*.33, end: PI2*.66, color:"green"});
    arcs.push({cx:100, cy:100, radius:75, start:PI2*.66, end: PI2, color:"blue"});
    // inner arcs
    arcs.push({cx:100, cy:100, radius:45, start:0, end: PI2*.55, color:"purple"});
    arcs.push({cx:100, cy:100, radius:45, start:PI2*.55, end: PI2*.75, color:"orange"});
    arcs.push({cx:100, cy:100, radius:45, start:PI2*.75, end: PI2, color:"maroon"});

    // visibly draw all arcs 

    for(var i=0;i<arcs.length;i++){
        defineArc(arcs[i]);
        context.strokeStyle=arcs[i].color;
        context.stroke();
    }

    // define BUT NOT VISIBLY DRAW an arc

    function defineArc(arc){
        context.beginPath();
        context.arc(arc.cx,arc.cy,arc.radius,arc.start,arc.end);
    }

    // handle mousemove events

    function handleMouseMove(e){

        // get mouse position
        mouseX=parseInt(e.clientX-offsetX);
        mouseY=parseInt(e.clientY-offsetY);

        // reset the results box to invisible
        context.clearRect(225,30,20,20);

        // hit-test each arc
        for(var i=0;i<arcs.length;i++){

            // define one arc
            defineArc(arcs[i]);

            // test that one arc
            // if "hit" fill the results box with that arc's color
            if(context.isPointInStroke(mouseX,mouseY)){
                context.fillStyle=arcs[i].color;
                context.fillRect(225,30,20,20);
                return;
            }

        }

    }

    // listen for mousemoves

    $("#canvas").mousemove(function(e){handleMouseMove(e);});

}); // end $(function(){});
</script>

</head>

<body>
    <h4>Move mouse over any arc</h4>
    <h4>When mouse is over arc, that color rect will appear</h4>
    <canvas id="canvas" width=300 height=300></canvas>
</body>
</html>

关于javascript - 识别圆弧上的事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20218603/

相关文章:

javascript - 函数内的 setTimeout 失败

javascript - 谷歌用多个独特的信息框映射多个标记

javascript - jquery - 折叠/扩展 div?

javascript - 使用 javascript onclick 事件更改 HTML 文件中的元素

javascript - 根据质量和弹跳系数计算球与球碰撞的速度和方向

javascript - 具有 React 的 datetime-local 值

javascript - jQuery - 同一页面上的多个图像过滤器

javascript - PHP 中如果为 null 则隐藏 div

html - 在 Canvas 上绘制正弦波

javascript - 无法像标准对象一样通过tiles[i-1]访问 "2d"对象的属性(javascript)