当Chrome中的coordnate非常大时,svg弧路径getBBox结果是错误的

时间:2017-01-04 05:56:40

标签: svg

路径元素0.0000711679458618164, 0.00007629334868397564,getBBox()结果宽度和高度为:"M 1040000 80 A 40 40 0 1 0 1040000 40"

如果将路径向左移动10000像素,则变为74.625, 79.99937438964844,则getBBox()结果宽度和高度为:function $$(id){return document.getElementById(id);} var b1 = $$("p1").getBBox(); $$("r1").innerHTML=('p1: width:'+b1.width +', height:'+ b1.height); //0.0000711679458618164, 0.00007629334868397564 var b2 = $$("p2").getBBox(); $$("r2").innerHTML=('p2: width:'+b2.width +', height:'+ b2.height); //74.625, 79.99937438964844

元素的宽度和高度不会改变,但getBBox()会给出不同的结果。

是什么原因以及如何避免这个问题? getBoundingClientRect()?

测试代码段:

<svg width="110" height="110" viewBox="1050000 0 110 110">
<path id="p1" d="M 1050000 80 A 40 40 0 1 0 1050000 40" stroke="#880000" stroke-width="1" fill="none"></path>
</svg>

<svg width="110" height="110" viewBox="1040000 0 110 110">
<path id="p2" d="M 1040000 80 A 40 40 0 1 0 1040000 40" stroke="#880000" stroke-width="1" fill="none"></path>
</svg>


<p id="r1"></p>
<p id="r2"></p>
MainWindow

1 个答案:

答案 0 :(得分:0)

已确认这是铬的错误:issue 678162。它最初是由Skia engine的代码错误引起的。修正是承诺。

只有某些版本的Chrome存在此错误。根据我的测试,Chrome 52还可以,Chrome 55有错误。

在我的情况下,我只需要将错误的bbox复用0x100000。

0.0000711679458618164 * 0x100000 == 74.625  
0.00007629334868397564 * 0x100000 == 79.99937438964844

最后,我使用自定义函数计算chrome的bbox。

此函数无法处理嵌套的svg(s)或嵌套转换。

function bbox (element) {
    var svg = element.farthestViewportElement,
        mtr = element.getScreenCTM().inverse(),
        bcr = element.getBoundingClientRect(),
        x1 = bcr.left, x2 = bcr.right,
        y1 = bcr.top, y2 = bcr.bottom,
        pts = [[x1,y1],[x1,y2],[x2,y1],[x2,y2]],
        pt = svg.createSVGPoint(), pt2,
        bb = {}, u;

    if(x1===0 && x2===0 && y1===0 && y2===0){
        return {x:0,y:0,width:0,height:0};
    }

    for(var i=0; i < 4; i++){
        pt.x = pts[i][0];
        pt.y = pts[i][1];
        pt2 = pt.matrixTransform(mtr);
        if(bb.xmin === u){
            bb.xmin = bb.xmax = pt2.x;
            bb.ymin = bb.ymax = pt2.y;
        }else{
            if(bb.xmin > pt2.x){
                bb.xmin = pt2.x;
            }else if(bb.xmax < pt2.x){
                bb.xmax = pt2.x;
            }
            if(bb.ymin > pt2.y){
                bb.ymin = pt2.y;
            }else if(bb.ymax < pt2.y){
                bb.ymax = pt2.y;
            }
        }
    }
    return {
        x: bb.xmin,
        y: bb.ymin,
        width: bb.xmax - bb.xmin,
        height: bb.ymax - bb.ymin
    };
}