4

我试图通过使用 getBBox() 方法获取边界框来根据文本的宽度和高度放置 SVG 文本元素。

如果文本使用网络安全字体,这在不同的浏览器中运行良好,但如果文本使用@font-face 和自定义网络字体设置样式,则在 Firefox (Mac) 和 Safari ( IOS)。它在 Safari (Mac) 和 Chrome (Mac) 中都能完美运行。

如果灰色框与文本的宽度相同,则它可以在该浏览器中使用。

有人知道如何在所有浏览器中获得正确的文本边界框宽度吗?

4

2 回答 2

3

浏览器在完成加载/应用之前正在计算边界框@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>

于 2012-09-20T15:54:37.350 回答
1

今天我遇到了类似的问题。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 代码,该代码可能会渲染一些东西,然后立即询问指标。

于 2013-01-22T02:27:08.353 回答