获取屏幕像素中旋转的SVG元素的边界?

时间:2012-08-30 18:24:16

标签: javascript svg bounding-box

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

// 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/

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

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

2 个答案:

答案 0 :(得分:4)

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

  • getBoundingClientRect()似乎适用于现代浏览器中的SVG元素,并且速度非常快,但结果可能因平台而有所不同(特别是如果你有足够的笔画宽度)。但是,对于@Sergiu来说,这并没有考虑到形状的变化,并且给出了旋转的边界框的边界,而不是实际的路径或对象,所以它可能非常不精确 - see criticism here。示例小提琴:http://jsfiddle.net/stevenbenner/6M5zf/

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

答案 1 :(得分:3)

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

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

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