identifying event on arc of circle

2019-09-02 14:05发布

I am a new user of html5 and using canvas to draw circle for one of my application. I have drawn several arcs to form a circle. it works fine. However my problem is that i want to associate a separate mouse event for each of the arc.

I goggled and found KinteticJS may be useful. I wish to know is there any other way that could be used to attached mouse event for every arc i created using the canvas. Please note i have used just one canvas there is no ghost canvas and I do not wish to use SVG. Below is the line of the code i used:

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

regards nad

1条回答
我只想做你的唯一
2楼-- · 2019-09-02 14:23

The quick answer is: No, but...

No:

Canvas does not "remember" anything drawn on itself--drawings are just color pixels added to the canvas. Canvas doesn't know the position of your arc and can't hit-test to see if the mousdown is inside that arc.

but...you can use math

You can use math to test if any point is inside the circle.

If any x/y is inside the outer radius of a circle and not inside the inner radius, then x/y is in the arc.

Given centerX,centerY,outerRadius,innerRadius:

Test if x,y is inside the outer radius:

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

Test if x,y is not inside the inner radius:

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

So if( isInsideOuterRadius && !isInsideInnerRadius){ alert("x/y is in your arc"); }

If you want to get fancy:

If you "remember" the arc for canvas, then canvas has a hit-test for that arc.

Context.isPointInStroke will test if an X/Y is located inside the most recently drawn path. If that most recent path is your arc, you can hit-test your arc.

For example, if you draw this arc:

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

You can hit-test that arc by supplying isPointInStroke with your mouse coordinates:

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

To test multiple arcs,

  1. Define one arc ( do context.arc without context.stroke )
  2. Test that arc with isPointInStroke
  3. Do #1 with the next arc

Except IE :(

isPointInStroke will work in Chrome and Firefox but won't yet work in Internet Explorer.

Alternatively for IE:

You can define a path around the outside of your arc and then use isPointInPath to test if your mouse is inside that path.

[ Update: and example ]

enter image description here

Here's a Fiddle (must view with Chrome or FF -- IE won't work):

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

Here's example code:

<!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>
查看更多
登录 后发表回答