【问题标题】:Hit-testing SVG shapes?命中测试 SVG 形状?
【发布时间】:2011-01-11 14:11:12
【问题描述】:

已实现部分 SVG 规范(Firefox 等)的浏览器免费为我们进行命中测试 - 如果我在 SVG 对象上附加 mousedown 侦听器,只要单击该形状,我就会收到通知。这太棒了,尤其是对于复杂的多边形形状。

我想知道是否有一种方法可以利用此功能进行更多的命中测试。我想知道给定的矩形是否与我的任何 SVG 形状相交。

例如,我向我的元素添加了 3 个复杂的多边形。现在我想知道矩形 (40, 40, 100, 100) 是否与它们中的任何一个相交。有谁知道我如何才能使用已经很强大的命中测试支持,而不是自己添加所有这些代码?

谢谢

【问题讨论】:

    标签: javascript svg hittest


    【解决方案1】:

    我不知道有什么方法可以与整个矩形相交。但是你可以与一个点相交,所以你可以建立一个更复杂的检查:

    var el= document.elementFromPoint(x, y);
    

    将在特定页面相对坐标处为您提供最高堆叠的元素。如果 SVG 内没有任何形状被命中,您将获得 <svg> 元素。

    这是一个非标准的Mozilla extension,但它也适用于 WebKit。不幸的是,尽管它存在于 Opera 中,但它不会在 <svg> 内部查找,因此在该浏览器上,该元素将始终是 SVGSVGElement。

    【讨论】:

    • 感谢您指出您的解决方案当时并不标准。它仍然是一个工作草案,但幸运的是,这种方法已成为(非常方便!)CSSOM 规范:dev.w3.org/csswg/cssom-view/#dom-document-elementfrompoint
    • elementFromPoint() 中使用的坐标是绝对坐标,所以除非您的 SVG 从 0,0 开始,否则您需要在绝对坐标和相对坐标之间进行调整
    【解决方案2】:

    SVG 1.1 DOM 的方法恰到好处(不幸的是,它还没有在 mozilla 中实现):

    var nodelist = svgroot.getIntersectionList(hitrect, null);
    

    有关完整的工作示例,请参阅here

    【讨论】:

    • 我想知道 getIntersectionList() 的 Chrome 实现 - 至少在 v70 中,当对象边界框与 hitrect 重叠时会考虑“交集”。不是对象呈现的内容,如w3c spec requires。所以不幸的是,它的应用非常有限。
    【解决方案3】:

    getIntersectionList 在 Opera 中运行良好。我的问题是 SVG 1.1 Full 规范中关于此的功能要求必须渲染元素(以及指针事件的可能目标)才能被检测为命中。不幸的是,这使得这些函数无法在当前只有部分世界可见的游戏世界中进行命中测试。

    【讨论】:

    • opacity:0visibility:hidden 仍然意味着有问题的元素是根据svg渲染的,但是这些元素将是不可见的。您应该能够调整 pointer-events 以很好地应用于这些不可见元素。
    【解决方案4】:

    Chrome 版本的 checkIntersection(和 getIntersectionList)测试元素边界框,而不是元素本身。我能够编写自己的 checkIntersection ,它通过使用画布和这种相当复杂的方法在 chrome 上工作,这种方法似乎适用于小矩形,但对于大矩形来说会很慢,所以它很适合命中测试。这种技术可以作为 Chrome 中 checkIntersection 的 polyfill,适用于小矩形和其他可能已经破坏了 checkIntersection 实现的浏览器。

    1. 创建一个使用包含 SVG 外部 HTML 的数据 URI 的图像(您可能还需要在其中包含样式规则),例如 so(此图像不必在页面中)。如果需要,您可以使用 onload 事件处理程序来确定何时加载。
    2. 创建一个画布以用于您的命中测试矩形(此画布不需要在页面中)

    要测试矩形是否与您的任何形状相交,请执行以下操作:

    1. 确保画布与矩形大小相同(设置其宽度和高度)
    2. 使用画布上下文clearRect()方法清除画布
    3. 在画布上的 -x, -y 处绘制 SVG,以便与画布重叠的图像部分对应于您要使用 drawImage() 测试的区域
    4. 使用上下文的getImageData() 获取画布的 ImageData。数据数组的每个第 4 个元素都是 alpha 字节,非零值意味着 SVG 的一部分与矩形重叠。如果第 4 个字节全部为 0,则您的 SVG 没有与矩形相交。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-26
      • 1970-01-01
      • 2017-05-03
      • 1970-01-01
      相关资源
      最近更新 更多