Yes, you are correct.
The new isPointInPath() works only on the centerline of a "fat" line--not the full width of the line.
It's more user friendly on closed shapes that are more than 1 pixel wide ;)
A Workaround for your exact question: Instead of drawing a fat line, draw a 20px wide rectangle.
Here is code and a Fiddle:
This code uses basic trigonometry to create a rectangle around a line. In the mousedown event handler, it redraws the rectangle transparently and then tests isPointInPath().
If you need to test a poly-line, you can use these same principles to make rectangle-lines for each segment of your poly-line.
<!doctype html> <html> <head> <link 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 width=310 height=115></canvas> </body> </html>
是的,你是正确的。
新的isPointInPath()只适用于中心线的“脂肪”,而不是完整的线的宽度。
更用户友好的封闭形状上超过1像素宽;)
一个解决方案为您的确切的问题:脂肪而不是画线,画一个20 px宽的矩形。
下面是代码和一个小提琴:
这段代码使用基本的三角线的创建一个矩形。在mousedown事件处理程序,它透明地重绘矩形,然后测试isPointInPath()。
如果您需要测试一个闸,您可以使用这些相同的原则为每一段rectangle-lines闸。
<!doctype html> <html> <head> <link 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 width=310 height=115></canvas> </body> </html>