2

この小さな例を見てください。クリックハンドラは、行の中央をクリックした場合にのみ機能します。この方法isPointInPathは、線の幅を考慮していないようです。この問題を解決する方法はありますか?

4

1 に答える 1

3

はい。それで合っています。

新しい isPointInPath() は、線幅全体ではなく、「太い」線の中心線でのみ機能します。

幅が 1 ピクセルを超える閉じた形状では、よりユーザー フレンドリーです ;)

正確な質問の回避策: 太い線を描く代わりに、幅 20 ピクセルの長方形を描きます。

ここにコードとフィドルがあります: http://jsfiddle.net/m1erickson/QyWDY/

このコードは、基本的な三角法を使用して、線の周りに四角形を作成します。mousedown イベント ハンドラーでは、四角形を透過的に再描画し、isPointInPath() をテストします。

ポリラインをテストする必要がある場合は、これらの同じ原則を使用して、ポリラインの各セグメントに長方形の線を作成できます。

<!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 ctx=canvas.getContext("2d");
    // get canvas's relative position
    var canvasOffset=$("#canvas").offset();
    var offsetX=canvasOffset.left;
    var offsetY=canvasOffset.top;

    // line specifications
    var x1=50;
    var y1=50;
    var x2=300;
    var y2=100;

    // draw the lineRectangle
    var lineRect=defineLineAsRect(x1,y1,x2,y2,20);
    drawLineAsRect(lineRect,"black");


    // overlay the line (just as visual proof)
    drawLine(x1,y1,x2,y2,3,"red");


    function drawLine(x1,y1,x2,y2,lineWidth,color){
        ctx.fillStyle=color;
        ctx.strokeStyle=color;
        ctx.lineWidth=lineWidth;
        ctx.save();
        ctx.beginPath();
        ctx.moveTo(x1,y1);
        ctx.lineTo(x2,y2);
        ctx.stroke();
        ctx.restore();
    }


    function drawLineAsRect(lineAsRect,color){
        var r=lineAsRect;
        ctx.save();
        ctx.beginPath();
        ctx.translate(r.translateX,r.translateY);
        ctx.rotate(r.rotation);
        ctx.rect(r.rectX,r.rectY,r.rectWidth,r.rectHeight);
        ctx.translate(-r.translateX,-r.translateY);
        ctx.rotate(-r.rotation);
        ctx.fillStyle=color;
        ctx.strokeStyle=color;
        ctx.fill();
        ctx.stroke();
        ctx.restore();
    }


    function defineLineAsRect(x1,y1,x2,y2,lineWidth){
        var dx=x2-x1; // deltaX used in length and angle calculations 
        var dy=y2-y1; // deltaY used in length and angle calculations
        var lineLength= Math.sqrt(dx*dx+dy*dy);
        var lineRadianAngle=Math.atan2(dy,dx);

        return({
            translateX:x1,
            translateY:y1,
            rotation:lineRadianAngle,
            rectX:0,
            rectY:-lineWidth/2,
            rectWidth:lineLength,
            rectHeight:lineWidth
        });
    }


    function handleMouseDown(e){
      mouseX=parseInt(e.clientX-offsetX);
      mouseY=parseInt(e.clientY-offsetY);

      // draw our lineRect
      drawLineAsRect(lineRect,"transparent");

      // test if hit in the lineRect
      if(ctx.isPointInPath(mouseX,mouseY)){
              alert('Yes');
      }
    }

    canvas.addEventListener("mousedown", handleMouseDown, false);

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

</head>

<body>
    <canvas id="canvas" width=310 height=115></canvas>
</body>
</html>
于 2013-03-23T15:08:39.423 に答える