7

我试图找到以屏幕像素为单位获取任意 SVG 元素边界框的最佳方法,以便正确覆盖 HTML 元素。到目前为止,我的方法是使用.getBBox().getCTM()检索对象的边界框和变换矩阵,然后将变换应用于边界框点,如该问题的已接受答案中所述。

// get the element
var el = $(selector)[0],
    pt = $(selector).closest('svg')[0].createSVGPoint();

// get the bounding box and matrix
var bbox = el.getBBox(),
    matrix = el.getScreenCTM();

pt.x = bbox.x;
pt.y = bbox.y;
var nw = pt.matrixTransform(matrix);
pt.x += bbox.width;
pt.y += bbox.height;
var se = pt.matrixTransform(matrix);

// make a div in the screen space around the object
var $div = $('<div class="bbox"/>').css({
        left: nw.x,
        top: nw.y,
        width: se.x - nw.x,
        height: se.y - nw.y
    })
    .appendTo('body');

你可以在这里看到我的测试:http: //jsfiddle.net/nrabinowitz/zr2jX/

但是,正如测试所示,当变换中包含旋转时,这种方法似乎会失败 - 看起来边界框是在旋转前计算的,因此获取旋转边界框的角不起作用。

如何正确计算转换元素的非旋转边界框?

4

2 回答 2

5

经过一番研究,以下是我发现的最佳选择:

  • getBoundingClientRect()似乎对于现代浏览器中的 SVG 元素效果很好,并且速度非常快,但结果可能因平台而异(尤其是如果您的笔画宽度很大)。但是,就@Sergiu 而言,这并没有考虑到形状的变化,而是为您提供了旋转边界框的边界,而不是实际的路径或对象,因此它可能非常不精确 -请参阅此处的批评。小提琴示例:http: //jsfiddle.net/stevenbenner/6M5zf/

  • 我的主要目标是获得边界矩形的位置角和中点,最后我决定使用旋转的边界框甚至可能比旋转形状的“真实”边界框更可取。我能够使用上述方法做到这一点,然后循环这些点以尽可能接近 N、S、E、W 位置。你可以在这里看到我的小提琴示例:http: //jsfiddle.net/nrabinowitz/sPtzV/

于 2012-09-05T17:06:49.900 回答
3

我认为这是不可能的,因为倾斜和旋转涉及轮廓变化,或者形状在两个轴上的投影看起来如何。

您可以计算忽略 CTM 旋转部分的转换矩阵,但是您不能保证新的 BBox 仍将围绕您的旋转元素。例如,如果您有一个圆,则旋转不会影响边界框的尺寸。另一方面,如果您有一个菱形作为基本路径,并将其旋转 45 度,最终它只是一个正方形,那么边界框就不同了:最初您测量的是对角线,而现在您必须获得一个测量边长的边界框。不管怎么用CTM,都不能考虑到形状的变化。

因此,轮换实际上非常重要,忽略它不是一种选择;但是只有局部边界框和变换矩阵并不能说明形状轮廓在旋转时如何变化。

于 2012-08-30T22:02:47.737 回答