如何知道 svg 路径上是否有任何 x 或 y 点
how to know if any x or y point is on svg path
我有一个 svg 路径,我想知道我的鼠标是否在 svg 路径上,如果是,我想将光标更改为鼠标指针。
这可以通过在路径上添加鼠标悬停 属性 以及 Recognize point(x,y) is inside svg path or outside 轻松完成
使用此解决方案。
但是有一个转折点,我上面有另一个透明层,因此我不能有这两种解决方案。
现在我正在制作顶层显示 none,它工作正常。但正因为如此,我的鼠标指针和我执行的操作(例如在鼠标移动时移动某个元素)很慢,
因此我想看看有没有其他更好的方法而不让显示等于none。
请找到 fiddle 示例,我想在 mypath 元素上将光标更改为指针,并且还希望 myline 在我将鼠标移到图层上时移动,我可以显示到 none暂时在层上,但我注意到在firefox上,线条移动不是那么流畅,
https://jsfiddle.net/shyam_bhiogade/9a7zuou2/6/
<svg width="400" height="400">
<g>
<path id="mypath" d="M10 200 L200 90 L200 200" fill="transparent" stroke="black" stroke-width="5" />
<rect class="interactiveArea" width="500" height="500" style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0);opacity:0.2" />
<line id="myline" x1="20" y1="0" x2="20" y2="400" stroke-width="2" stroke="black" />
</g>
</svg>
我已经使用了https://bl.ocks.org/mbostock/8027637给出的解决方案,它returnsx和y点到路径的距离,如果距离小于1px或笔划宽度,我考虑x 和 y 点在路径上。
function closestPoint(pathNode, point) {
var pathLength = pathNode.getTotalLength(),
precision = 8,
best,
bestLength,
bestDistance = Infinity;
// linear scan for coarse approximation
for (var scan, scanLength = 0, scanDistance; scanLength <= pathLength; scanLength += precision) {
if ((scanDistance = distance2(scan = pathNode.getPointAtLength(scanLength))) < bestDistance) {
best = scan, bestLength = scanLength, bestDistance = scanDistance;
}
}
// binary search for precise estimate
precision /= 2;
while (precision > 0.5) {
var before,
after,
beforeLength,
afterLength,
beforeDistance,
afterDistance;
if ((beforeLength = bestLength - precision) >= 0 && (beforeDistance = distance2(before = pathNode.getPointAtLength(beforeLength))) < bestDistance) {
best = before, bestLength = beforeLength, bestDistance = beforeDistance;
} else if ((afterLength = bestLength + precision) <= pathLength && (afterDistance = distance2(after = pathNode.getPointAtLength(afterLength))) < bestDistance) {
best = after, bestLength = afterLength, bestDistance = afterDistance;
} else {
precision /= 2;
}
}
best = [best.x, best.y];
best.distance = Math.sqrt(bestDistance);
return best;
function distance2(p) {
var dx = p.x - point[0],
dy = p.y - point[1];
return dx * dx + dy * dy;
}
}
我有一个 svg 路径,我想知道我的鼠标是否在 svg 路径上,如果是,我想将光标更改为鼠标指针。
这可以通过在路径上添加鼠标悬停 属性 以及 Recognize point(x,y) is inside svg path or outside 轻松完成 使用此解决方案。
但是有一个转折点,我上面有另一个透明层,因此我不能有这两种解决方案。
现在我正在制作顶层显示 none,它工作正常。但正因为如此,我的鼠标指针和我执行的操作(例如在鼠标移动时移动某个元素)很慢,
因此我想看看有没有其他更好的方法而不让显示等于none。
请找到 fiddle 示例,我想在 mypath 元素上将光标更改为指针,并且还希望 myline 在我将鼠标移到图层上时移动,我可以显示到 none暂时在层上,但我注意到在firefox上,线条移动不是那么流畅,
https://jsfiddle.net/shyam_bhiogade/9a7zuou2/6/
<svg width="400" height="400">
<g>
<path id="mypath" d="M10 200 L200 90 L200 200" fill="transparent" stroke="black" stroke-width="5" />
<rect class="interactiveArea" width="500" height="500" style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0);opacity:0.2" />
<line id="myline" x1="20" y1="0" x2="20" y2="400" stroke-width="2" stroke="black" />
</g>
</svg>
我已经使用了https://bl.ocks.org/mbostock/8027637给出的解决方案,它returnsx和y点到路径的距离,如果距离小于1px或笔划宽度,我考虑x 和 y 点在路径上。
function closestPoint(pathNode, point) {
var pathLength = pathNode.getTotalLength(),
precision = 8,
best,
bestLength,
bestDistance = Infinity;
// linear scan for coarse approximation
for (var scan, scanLength = 0, scanDistance; scanLength <= pathLength; scanLength += precision) {
if ((scanDistance = distance2(scan = pathNode.getPointAtLength(scanLength))) < bestDistance) {
best = scan, bestLength = scanLength, bestDistance = scanDistance;
}
}
// binary search for precise estimate
precision /= 2;
while (precision > 0.5) {
var before,
after,
beforeLength,
afterLength,
beforeDistance,
afterDistance;
if ((beforeLength = bestLength - precision) >= 0 && (beforeDistance = distance2(before = pathNode.getPointAtLength(beforeLength))) < bestDistance) {
best = before, bestLength = beforeLength, bestDistance = beforeDistance;
} else if ((afterLength = bestLength + precision) <= pathLength && (afterDistance = distance2(after = pathNode.getPointAtLength(afterLength))) < bestDistance) {
best = after, bestLength = afterLength, bestDistance = afterDistance;
} else {
precision /= 2;
}
}
best = [best.x, best.y];
best.distance = Math.sqrt(bestDistance);
return best;
function distance2(p) {
var dx = p.x - point[0],
dy = p.y - point[1];
return dx * dx + dy * dy;
}
}