使用 SVG 和 JavaScript 检查多边形中的点?
我有一张地图,通过将不同颜色的区域转换为路径,将光栅图形转换为 SVG 文件。
我知道如何在给定边缘数组的情况下进行基本的多边形内点检查,但是 svg:path 元素表示多个多边形以及掩模(以考虑海洋等)并提取该信息通过解析 d 属性似乎相当严厉。
是否有一个 JS 库可以让我简化该检查?我基本上想创建随机点,然后检查它们是在陆地上(即多边形内部)还是在水中(即外部)。
由于 SVG 元素似乎允许鼠标事件处理,我认为这应该不是什么大问题(即,如果您可以判断鼠标指针是否位于元素顶部,那么您已经解决了 point-in-多边形问题)。
编辑:让问题变得有点复杂,我应该提到 svg:path 元素似乎基于曲线而不是直线,因此只需解析 d 属性即可创建一个边缘数组似乎不是一个选择。
由于元素可以采用 fill
属性,因此在画布上渲染 SVG 然后查找给定点的像素颜色值的 ghetto 方法是可行的,但这看起来真的非常非常困难。可怕的方法来做到这一点。
I have a map that I converted from a raster graphic into an SVG file by converting the differently coloured areas into paths.
I know how to do a basic point-in-polygon check given an array of edges, but the svg:path
elements represent multiple polygons as well as masks (to account for seas etc) and extracting that information by parsing the d
attribute seems rather heavy-handed.
Is there a JS library that allows me to simplify that check? I basically want to create random points and then check whether they are on land (i.e. inside the polygons) or water (i.e. outside).
As SVG elements seem to allow for mouse event handling, I would think that this shouldn't be much of a problem (i.e. if you can tell whether the mouse pointer is on top of an element, you are already solving the point-in-polygon problem).
EDIT: Complicating the matter a bit, I should mention that the svg:path
elements seem to be based on curves rather than lines, so just parsing the d
attribute to create an array of edges doesn't seem to be an option.
As the elements can take a fill
attribute, a ghetto approach of rendering the SVG on a canvas and then finding the colour value of the pixel at the given point could work, but that seems like a really, really awful way to do it.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
命中测试 SVG 形状? 上的答案可能会帮助您完成此任务。缺少浏览器支持存在问题,但您也许可以使用 svgroot.checkIntersection 来测试多边形形状内的一个小矩形(也许甚至 0 宽度/高度也可以?)。
The answers on Hit-testing SVG shapes? may help you in this quest. There are issues with missing browser support, but you could perhaps use svgroot.checkIntersection to hit test a small (perhaps even 0 width/height would work?) rectangle within your polygon shape.
我建议的作为最后手段的方法似乎是解决这个问题的最简单的方法。
我发现一个不错的 JS 库,可以轻松在画布上渲染 SVG。渲染 SVG 后,只需在要检查的点处调用 2D 上下文的
getImageData
方法即可获取 1x1 区域。我想,如果您的 SVG 比我使用的 SVG 更复杂(您必须逐字节检查 RGBA 值),那么创建带有颜色编码的 SVG 副本会更容易检查。当您实际上检查光栅图像的像素时,这感觉非常黑客,但性能似乎足够不错,并且颜色检查可以以允许杂质(例如靠近边缘)的方式编写。
我想如果您想要相对坐标,您可以尝试创建一个 1 比 1 大小的画布,然后将像素坐标除以画布尺寸。
如果有人提出更好的答案,我会接受。在那之前,这个可以作为一个占位符,以防有人带着同样的问题来到这里寻找简单的解决方案。
The approach I suggested as a last resort seems to be the easiest solution for this problem.
I found a nice JS library that makes it easy to render SVG on a canvas. With the SVG rendered, all it takes is a call to the 2D context's
getImageData
method for a 1x1 region at the point you want to check. I guess it helps to create a copy of the SVG with colour coding to make the check easier if your SVG is more complex than the one I'm using (you'll have to check the RGBA value byte-by-byte).This feels terribly hackish as you're actually inspecting the pixels of a raster image, but the performance seems to be decent enough and the colour checks can be written in a way that allows for impurities (e.g. near the edges).
I guess if you want relative coordinates you could try creating a 1-to-1 sized canvas and then divide the pixel coordinates by the canvas dimensions.
If somebody comes up with a better answer, I'll accept it instead. Until then, this one serves as a placeholder in case someone comes here with the same problem looking for an easy solution.