我需要一种机制来检测具有不同笔画宽度的线条,曲线和折线的鼠标悬停事件,我已经为矩形和椭圆形做了这样的机制,所以我不是新的canvas API。我确实绘制了所有绘制的对象并检测它们上方的鼠标位置,当矩形或椭圆的笔划宽度超过1个像素时,我展开路径以使其包含边框。对于直线和折线,当我的线宽为20像素时,我很难理解如何展开它们。
我的问题是:如何在某个形状路径中变换线条,曲线和折线,以便此路径可以包含它们的所有宽度?
我需要创建的路径包含此图像中用黑色表示的线条/曲线宽度。
----------更多信息----------
我会尝试简化问题: 我们有2个点(在下图中用红色表示),它们形成一条具有特定公式(y = mx + n)的线,我需要擦除通过这两个初始点的垂直线的公式,之后,有必要确定“蓝色”点的位置,这些点位于context.lineWidth值的一半的距离,当确定了所有点后,可以使用moveTo()创建一个新路径, lineTo()序列。此方法应适用于使用控制点的二次和贝塞尔曲线。这个问题只存在于这些数学计算中。
答案 0 :(得分:3)
我在math.stackexchange here上找到了解决方案,此解决方案仅适用于行,但它适用于具有某些特定修改的曲线和折线。首先,我们需要确定通过两个首字母点的线的公式:
第1步
我们的观点:P1(x1,y1)和P2(x2,y2)
点与邻居之间的距离:d
一般形式:Ax + By + C = 0
其中:A = y2 - y1; B = x1 - x2; C = x2y1 - x1y2。
之后,有必要以简短形式定义此公式:
第2步
简短形式:y = mx + n
式中:m = - A / B; n = - C / B.(当B!= 0时)
如果A == 0,那么我们得到公式:y = C(我们有一条水平线的情况)
如果B == 0,那么我们得到公式:x = C(我们有一条垂直线的情况)
当我们有线的斜率时,我们需要垂直线的斜率:
第3步
Perpendiculat线斜率:m2 = -1 / m
如果A == 0或B == 0,请转到步骤4
现在我们需要得到两个初始点的邻居点:
第4步
我会注意到第一个点的P1N1,P1N2和第二个点的P2N1和P2N2的相邻点
对于特殊情况(水平和垂直线,当A == 0或B == 0)时,我们将:
对于A == 0(水平线):
P1N1(x1,y1-d / 2); P1N2(x1,y1 + d / 2); P2N1(x2,y2 + d / 2); P2N2(x2,y2-d / 2)。
对于B == 0(垂直线):
P1N1(x1 - d / 2,y1); P1N2(x1 + d / 2,y1); P2N1(x2 + d / 2,y2); P2N2(x2 - d / 2,y2)。
对于其他情况(A!= 0和B!= 0):
P1N1:
x =(d / 2)/ Math.sqrt(1 + Math.pow(m2,2))+ x1;
y =(m2 *(d / 2))/ Math.sqrt(1 + Math.pow(m2,2))+ y1;
P1N2:
x = - (d / 2)/ Math.sqrt(1 + Math.pow(m2,2))+ x1;
y = - (m2 *(d / 2))/ Math.sqrt(1 + Math.pow(m2,2))+ y1;
P2N1:
x =(d / 2)/ Math.sqrt(1 + Math.pow(m2,2))+ x2;
y =(m2 *(d / 2))/ Math.sqrt(1 + Math.pow(m2,2))+ y2;
P2N2:
x = - (d / 2)/ Math.sqrt(1 + Math.pow(m2,2))+ x2;
y = - (m2 *(d / 2))/ Math.sqrt(1 + Math.pow(m2,2))+ y2;
如果要在应用程序中实现这些公式,则应缓存一些结果以提高性能。
答案 1 :(得分:2)
如果bezier曲线具有以下形式。
x(t) = x0 + x1*t + x2*t*t + x3*t*t*t
y(t) = y0 + y1*t + y2*t*t + y3*t*t*t
然后你必须compute the derivatives,它会在任何一点给出切线。
x'(t) = x1 + 2*x2*t + 3*x3*t*t
y'(t) = y1 + 2*y2*t + 3*y3*t*t
任何时候和正常线。法线是任意点的垂线,也是两点的支撑。
(-y'(t), x'(t))
((y'(t), -(x'(t))
答案 2 :(得分:0)
您是否尝试过使用Canvas 2D API的.isPointInStroke()方法:
ctx.isPointInStroke(x, y);
ctx.isPointInStroke(path, x, y);
看看: https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/isPointInStroke