在渲染之前获取 SVG 中的文本宽度

Posted

技术标签:

【中文标题】在渲染之前获取 SVG 中的文本宽度【英文标题】:getting text width in SVG prior to rendering 【发布时间】:2013-10-15 10:25:06 【问题描述】:

我想在 SVG 中的文本周围放置一个矩形。 我知道文本的高度(text 元素的font-size 属性)。但宽度取决于实际内容。使用 getBBox()getComputedTextLength() 应该可以。但这仅在渲染后有效。

有没有办法以其他方式指定?例如定义相对于其他值的xwidth 属性?我在 SVG 规范中没有找到类似的东西。

【问题讨论】:

渲染后测量有什么问题? @RobertLongson 代码复杂度和视觉跳跃。我正在动态生成整个文档。所有对象都应该准备好,然后添加到文档中,然后渲染。在渲染后计算时,我必须渲染未完成的对象,然后在渲染后更改它们。这会导致视觉跳跃。 将您的代码添加到问题中?您是否尝试获取尚未插入到文档中的元素的 bbox 和文本长度? 视觉跳跃很容易修复。将事物设为可见性=“隐藏”,然后在完成后取消隐藏。 @ErikDahlström 我还没有任何代码。我仍在寻找它。你是对的,我想获得尚未插入文档的元素的 bbox 和/或文本长度。由于这是不可能的,我正在寻找一些解决方法。也许有属性值来指定与任意其他元素的长度相关的长度。 【参考方案1】:

推测文本结束的位置大概需要与渲染本身实现的基本代码路径大致相同 - 根据字体和样式等遍历每个字符的宽度......因为我不知道 SVG 标准定义了一种方法为了直接获取这些信息而不进行实际的完整渲染,直到此类方法出现或被其他人报告在这里,方法应该是在进行实际渲染之前不可见地渲染。

您可以在隐藏层(z-index、不透明度和其他东西)或可见视口之外执行此操作,以在实验中效果最佳者为准。您只需要让浏览器进行渲染即可找出答案,因此您为此隐身渲染,然后使用getComputedTextLength()

【讨论】:

【参考方案2】:

我知道这是旧的,但有一些想法:

    如果您可以选择等宽字体,您可以通过简单的常数乘以字形计数来知道您的宽度

    如果您一定要使用比例字体,您可以找到一个平均字形大小,像使用单空间一样进行数学运算,并留出足够的填充。或者,您可以使用 text 元素 textLength 属性填充填充。如果仔细选择常数,结果不会很令人不快。

编辑:因为 matanster 发现它是 hacky

    使用getComputedTextLength() 预先确定字形宽度并构建查找表。缺点是它不考虑字距调整,但如果您的缓存大小不是问题,您可以在此查找中附加字形对宽度。

除此之外,还要找到一些方法来进行服务器端渲染:Is there a way to perform server side rendering of SVG graphics using React?

【讨论】:

可以说这有点 hacky 不是吗?【参考方案3】:

可以将canvasmeasureText() 一起使用:

// Get text width before rendering
const getTextWidth = (text, font) => 
  const element = document.createElement('canvas');
  const context = element.getContext('2d');
  context.font = font;
  return context.measureText(text).width;


// Demo
const font = '16px serif';
const text = 'My svg text';
const textWidth = getTextWidth(text, font);

document.body.innerhtml = `
  <svg>
    <text x="0" y="20" font="$font">$text</text>
    <rect x="0" y="30"   fill="red" />
   </svg>
`;

改编自https://***.com/a/31305410/1657101

【讨论】:

以上是关于在渲染之前获取 SVG 中的文本宽度的主要内容,如果未能解决你的问题,请参考以下文章

如何在 IE 11 中的 Image.load 上获取 SVG 的宽度和高度

如何获取 svg:g 元素的宽度

使用 SVG 渲染 Pdf 后,文本内容副本无法正常工作

在渲染到布局之前获取文本视图的高度

渲染前Javafx文本的尺寸

使用 SVG 进行 2D 渲染和放大