我试图通过使用 getBBox() 方法获取边界框来根据文本的宽度和高度放置 SVG 文本元素。
如果文本使用网络安全字体,这在不同的浏览器中运行良好,但如果文本使用@font-face 和自定义网络字体设置样式,则在 Firefox (Mac) 和 Safari ( IOS)。它在 Safari (Mac) 和 Chrome (Mac) 中都能完美运行。
如果灰色框与文本的宽度相同,则它可以在该浏览器中使用。
有人知道如何在所有浏览器中获得正确的文本边界框宽度吗?
我试图通过使用 getBBox() 方法获取边界框来根据文本的宽度和高度放置 SVG 文本元素。
如果文本使用网络安全字体,这在不同的浏览器中运行良好,但如果文本使用@font-face 和自定义网络字体设置样式,则在 Firefox (Mac) 和 Safari ( IOS)。它在 Safari (Mac) 和 Chrome (Mac) 中都能完美运行。
如果灰色框与文本的宽度相同,则它可以在该浏览器中使用。
有人知道如何在所有浏览器中获得正确的文本边界框宽度吗?
浏览器在完成加载/应用之前正在计算边界框@font-face
,假设您不需要 IE,您可以将 BBox 计算函数包装在一个document.fonts.ready
承诺中......
document.fonts.ready.then(() => const bbox = textEl.getBBox());
这是一个展示问题和修复的工作示例:
const xmlns = "http://www.w3.org/2000/svg";
const correct = document.getElementById("correct");
const incorrect = document.getElementById("incorrect");
visualizeBBox(incorrect);
document.fonts.ready.then(()=> visualizeBBox(correct));
function visualizeBBox(el){
const bbox = el.getBBox();
const rect = document.createElementNS(xmlns, "rect");
for (prop in bbox) rect.setAttribute(prop, bbox[prop]);
document.querySelector("svg").appendChild(rect);
}
svg text {
font-family: 'Diplomata SC', serif;
}
svg rect {
stroke: red;
fill: none;
}
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Diplomata+SC&display=swap" rel="stylesheet">
<svg xmlns="https://www.w3.org/2000/svg" width="600" height="400">
<text x="0" y="40" font-size="24" id="correct">Correct dimensions</text>
<text y="100" font-size="24" id="incorrect">Incorrect dimensions</text>
<svg>
今天我遇到了类似的问题。Duopixel 是正确的,getBBox() 可能会返回可能出乎意料的矩量度,因为尚未加载外部字体,而是使用了一些标准字体。
WebKit 中的问题(在 Chrome 24.0.1312.52 和 26.0.1389.0 canary 中测试)是浏览器延迟外部字体加载,直到它首次在页面上的任何位置有效使用。因此,即使您等待 onreadystatechange 变为“完成”,您也不能保证在调用 getBBox() 时准备好字体指标 - 您可能仍然是第一个渲染带有外部字体样式的文本,将其插入文档并立即调用的人getBBox() 就可以了(我的情况)。
我的解决方法不是直接调用 mySVGInitCode() 而是这样做:
$("body").append(
$("<div/>")
.attr("class", "force-external-font-loading")
.attr("style", "font-family: \"xkcd\";visibility:hidden;position:absolute")
.text("x")
);
setTimeout(function(){ mySVGInitCode() }, 100); // 100ms is just arbitrary waiting time which should be sufficient for fetching the external font on a fast network, anyone has a better solution?
如您所见,我动态插入绝对定位的样式文本以强制加载外部字体(可见性:隐藏在这里很重要,而不是显示:无)。然后我等待一段时间,然后执行我的 SVG 代码,该代码可能会渲染一些东西,然后立即询问指标。