TLDR;
我想使用svg.checkIntersection()
,但很难得到/计算函数所需的正确的边框。在SVG元素的初始坐标下,获得转换的SVG元素的边界框的最干净方法是什么?
我试图在代码生成的SVG中检查重叠的text
元素。text
元素定位在(0, 0)
,并使用transform
属性操作到正确的位置,如下所示:
<svg xmlns="http://www.w3.org/2000/svg" id="svg0" viewBox="-100 -100 200 200">
<text id="t0" transform="rotate(-30) translate(15 -5)">Text 0</text>
<text id="t1" transform="rotate(-10) translate(15 -10)">Text 1</text>
<!-- do they overlap? -->
</svg>
请注意,所使用的特定转换不是可预先确定的。
因此,人们自然会尝试这样做:
const mySvg = document.querySelector("#svg0");
const text0 = mySvg.querySelector("#t0");
const text1 = mySvg.querySelector("#t1");
const isOverlap = mySvg.checkIntersection(text0, /* bounding box of text1 */);
麻烦的是,没有容易的方法来获得这个包围盒。W3定义声明:
这些值位于当前“svg”元素的初始坐标系中。
因此:
getBoundingClientRect()
是不合适的,因为这个SVG打算成为HTML DOM
中的一个组件,而getBoundingClientRect()
将返回HTML坐标系中的值。getBBox()
并不有用,因为它返回元素的本地坐标系中的值,这与所应用的transform
的初始坐标不同。getCTM()
似乎很有用,但是手动应用矩阵来获得包围框看起来像很多手写的数学。如果可能的话,我想避免这样做。所以最后..。
考虑到没有直接的内置方法,在svg.checkIntersection()
中获得元素边界框的最干净和/或最简单的方法是什么?
发布于 2020-06-27 20:12:43
最后,我使用了OSUblake 这里提供的解决方案,并结合了一个简单的矩形相交算法这里。
基本上,首先计算从对象坐标空间到SVG坐标空间的转换矩阵:
const matrix = svg.getScreenCTM().inverse().multiply(element.getScreenCTM());
然后将矩阵应用于元素边界框的所有四个点,并从最小值和最大值计算x
、y
、width
和height
。
const p = svg.createSVGPoint();
p.x = r.x;
p.y = r.y;
const pA = p.matrixTransform(matrix);
p.x = r.x + r.width;
p.y = r.y;
const pB = p.matrixTransform(matrix);
...
关于充分实施,请参阅原始员额。
这实际上是一个很大的数学函数,这是我真正想要避免的。但最终它在不需要DOM更改的情况下完成任务。结合简单的交集函数,它也让我抛弃了svg.checkIntersection()
,它最初给出了奇怪的结果(在Chrome83上测试)。
https://stackoverflow.com/questions/62526758
复制