Firefox中使用getBBox()获取SVG tspan高度返回错误值
SVG tspan getBBox() 跨浏览器兼容性问题解决
问题现象
- 调用
tspan#t18yiifj的子元素getBBox()时,Firefox返回高度约18(错误),Chrome/Edge返回约450(正确) - 获取
tspan#t18yiifj及其父元素的getBBox()时,所有浏览器均返回height:0, width:0, x:0, y:0
相关代码
SVG片段
<g id="dynam_10206" class="dynam" style="cursor: pointer;" fill="rgba(0, 0, 0, 1.0)" stroke="rgba(0, 0, 0, 1.0)"> <text x="7465" y="1690" font-size="0px"> <tspan id="tcbd4q9" class="text"> <tspan font-size="405px" class="text">cresc</tspan> </tspan> <tspan id="supplied_1234a" class="supplied highlighted"> <tspan id="t18yiifj" class="text"> <tspan font-size="405px" class="text">endo</tspan> </tspan> </tspan> </text> </g>
测试JS代码
// 子元素BBox差异 const elem = document.getElementById('t18yiifj'); const elemChild = elem.querySelectorAll("tspan[font-size]")[0]; console.log("elemChild BBox:", elemChild.getBBox()); // 父元素BBox全为0 console.log("elem BBox:", elem.getBBox()); const elemParent = elem.closest('.supplied'); console.log("elemParent BBox:", elemParent.getBBox());
问题原因
- 根
<text>元素设置了font-size:0px,Firefox在计算子tspan的BBox时,因排版规则差异错误继承了根元素的0字号计算逻辑,导致高度计算异常 - 父级
tspan(#t18yiifj和.supplied)仅作为容器,未直接设置font-size也无直接文本内容,浏览器判定其无渲染内容,返回空BBox
解决方案
方案1:修正根text元素的font-size设置
避免在根<text>上设置font-size:0px,改用合理的基础字号(子元素仍可覆盖):
<text x="7465" y="1690" font-size="1px"> <!-- 原tspan内容保持不变 --> </text>
修改后Firefox能正确识别子tspan的字号,计算出符合预期的BBox。
方案2:使用getBoundingClientRect()替代getBBox()
getBoundingClientRect()返回元素相对视口的边界矩形,跨浏览器一致性更强。如需转换为SVG内部坐标,可结合getScreenCTM()处理:
const elemChild = document.querySelector('#t18yiifj tspan[font-size]'); const rect = elemChild.getBoundingClientRect(); const svg = elemChild.closest('svg'); const ctm = svg.getScreenCTM().inverse(); // 转换为SVG内部坐标 const svgBBox = { x: rect.x * ctm.a + rect.y * ctm.c + ctm.e, y: rect.x * ctm.b + rect.y * ctm.d + ctm.f, width: rect.width * ctm.a, height: rect.height * ctm.d }; console.log("转换后的SVG BBox:", svgBBox);
方案3:给容器tspan添加基础排版上下文
若需父级tspan返回有效BBox,可给其设置font-size(子元素仍可覆盖):
<tspan id="t18yiifj" class="text" font-size="405px"> <tspan font-size="405px" class="text">endo</tspan> </tspan>
此时父tspan拥有排版上下文,计算BBox时会包含子元素的范围。
内容的提问来源于stack exchange,提问作者oleksii.sapov-erlinger
相关产品推荐
相关产品推荐

