如何获取SVG文本的实际高度(不是边界框高度)

时间:2017-02-20 07:42:49

标签: javascript html svg

我希望能够计算SVG中文本(或跨度)元素占用的实际高度。

现在,我通过计算对象边界框的高度来实现这一点,但是它采用了字体字形的高度,因此我放在元素中的任何文本都具有相同的高度,如下例所示:

var minA = document.getElementById('min-a'),
    capA = document.getElementById('cap-a'),
    minAHeight = document.getElementById('min-a-height'),
    capAHeight = document.getElementById('cap-a-height')
;

minAHeight.innerHTML = minA.getBBox().height;
capAHeight.innerHTML = capA.getBBox().height;
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 180 80">
  <text id="min-a" x="20" y ="20">a</text>
  <text id="cap-a" x="20" y ="50">Â</text>
  <text id="min-a-height" x="70" y ="20"></text>
  <text id="cap-a-height" x="70" y ="50"></text>
<svg>

如何计算每个元素的实际高度?

4 个答案:

答案 0 :(得分:1)

对于svg中的文本,您可以根据需要手动设置字体大小

<svg:text #t
  [attr.x]="xoffset"
  [attr.y]="yoffset"
  font-family="Courier"
  [attr.font-size]="fontsize">
  {{bottom_text.toUpperCase()}}
</svg:text> 

这将为您的svg元素提供一个静态大小的字体。您还可以选择使用浏览器开发工具在实际元素上“检查元素”。在选择中显示所选元素的宽度和高度。 (例如,参见图片)这种“悬停在”高度将包括与元素相关联的任何填充,但是检查元素上列出的属性它还应该包含仅字体高度“font-size”enter image description here < / p>

答案 1 :(得分:1)

@Fuzzyma走在正确的轨道上。您想使用OpenType.js并在浏览器中加载字体。

// These two match whatever you are doing in your code
const text = 'Hello'
const fontSize = 20

// Load font - I find ttf work better than woff (has extra data for other calculations if needed)
opentype.load(`/path/to/font.ttf`, (err, font) => {

   // Actual dimensions of the text
   const bb = font.getPath(text, 0, 0, fontSize)

})

这将为您提供真正的边界框,可满足您的需求。如果您确实需要使用它来了解文本上的屏幕位置,那么它可能会更具挑战性。

它的要点是你需要匹配基线。该字体包含ascender / descender(font.tables.hhea.asscenderfont.tables.hhea.descender),一旦转换为em(font.tables.head.unitsPerEm * fontSize),总计字体大小。

有了这个,你需要浏览字体的每个字形并获得yMaxyMinxMinxMax。使用ascender / descender和Y coords来确定你的新bb离“假”边界框(DOM返回的边界框)有多远。左边和右边更容易,除了一些奇怪的字体,其字母可以超出其邻居(边缘情况)。

在浏览器的基础上添加每个浏览器的垂直偏移...这可以通过获取SVG文本元素的y属性(即-5)来提取 - 然后取你的字体大小,除以这个y的一半和一个,你有浏览器使用的垂直偏移量(在我们的例子中为5)。每个浏览器都不同,但y坐标反映了这一点。

答案 2 :(得分:0)

为此,您需要加载并解析字体文件,并使用存储在其中的字形来计算bouding框。 在服务器上,您可以使用opentype.jsfontkit加载字体并获取某些文本的边界框。

但是在客户端上,您需要自己解析字体文件。对于svg字体来说这很容易,但是当你处理二进制格式(例如truetype)时会变得更难 但是当你设法做到这一点时,你可以绘制glypgs的路径并使用浏览器getBBox()来计算你想要的边界框。

这就是理论 - 但我的猜测是,比编写自己的字体文件解析器更容易解决这个问题。

如果有人知道,请随时修改!

答案 3 :(得分:0)

不确定这是否能解决您的问题,但我能够使用画布 measureText 方法计算单个字母的尺寸:

function getLetterSize(letter) {
    const ctx = document.createElement("canvas").getContext("2d");
    ctx.font = "25px sans-serif";
    const dim = ctx.measureText(letter);
    return {
        width: dim.actualBoundingBoxRight + dim.actualBoundingBoxLeft,
        height: dim.actualBoundingBoxAscent + dim.actualBoundingBoxDescent
    };
}