计算字体字形的确切大小

时间:2014-06-20 10:59:40

标签: node.js svg d3.js glyph

我需要一种方法来找到字形相对于其边界框的确切大小和位置。

我们正在使用D3.js创建一个带有标题,较小的署名和短正文的SVG。差不多这个:

  

Lorem ipsum

     

Lorem ipsum dolor

     

Lorem ipsum dolor sit amet,
  consectetur adipisicing elit,
  sed do eiusmod tempor
  incididunt ut labore et dolore
  magna aliqua

如本示例所示,无论字体大小如何,我都需要将文本左对齐。

问题是每个线条边界框都是对齐的而不是字形。这使标题看起来缩进。如何计算边界框和字形之间的空间,以便我可以正确对齐文本?

一位同事坐下来手动测量了这个英文字体,效果非常好。我们可以在Adobe Illustrator中执行此操作,但我们需要英文,中文和阿拉伯字体的信息。手工做这或多或少是不可能的。

我能想到的唯一解决方案是在canvas元素中键入每个字符并映射每个像素以查看字形的开始和结束位置。

我认为理想的是一种使用SVG字体路径信息来查找极端的方法,这样我们就可以得到确切的数字而不是估计值。我们的估计有很大的误差。有没有办法用node.js做到这一点?

SVG的示例:

<svg viewBox="0,0,1008,1424" height="1052px" width="744px" version="1.1" 
    xmlns:xlink="http://www.w3.org/1999/xlink" 
    xmlns="http://www.w3.org/2000/svg">
    <g transform="translate(50,150)" class="container">
        <g transform="translate(0,205)" class="textContainer">
            <g fill="white" font-family="serif" font-size="" class="header">
                <text>
                    <tspan y="147.7104222717285" style="" font-size="208" 
                        x="-21.8359375">Lorem ipsum</tspan>
                </text>
                <text>
                    <tspan y="201.46275431823733" style="" font-size="45" 
                        x="-4.72412109375">Lorem ipsum dolor</tspan>
                </text>
            </g>
            <g lengthAdjust="spacingAndGlyphs" textLength="297" fill="white" 
                transform="translate(0,214)" font-family="sans-serif" 
                class="paragraph" font-size="14">
                <text y="16.8" x="0">Lorem ipsum dolor sit amet,</text>
                <text y="33.6" x="0">consectetur adipisicing elit,</text>
                <text y="50.4" x="0">sed do eiusmod tempor</text>
                <text y="67.2" x="0">incididunt ut labore et dolore</text>
                <text y="84" x="0">magna aliqua</text>
            </g>
        </g>
    </g>
</svg>

我们需要计算xy元素的texttspan值,特别是负x值。注意:我们实际上并未使用serifsans-serif字体系列,而是使用自定义字体。我不认为英文字体是在创建Web时使用的。我们使用fontsquirrel.com来创建SVG字体文件。

更新

SVG字体似乎是最合理的选项,因为您可以在节点中读取文件中的所有路径信息。你只需要解释它。但我们发现,并决定使用opentype.js,它与otf和ttf字体一起使用。

我仍然想知道这是否与SVG字体完全相同。

2 个答案:

答案 0 :(得分:1)

我认为这可能会做你想要的。请注意,它需要jQuery并且有点hacky。您可能想在css对象中设置line-height。

function glyphSize(glyph,css){
  var span = $('<div>');
  span.text(glyph);
  span.css({
    display:'inline-block',
    position:'fixed',
    top:'100%'
  }).css(css);

  $('body').append(span);
  var out = {
    width:span.width(),
    height:span.height()
  } 
  span.remove();
  return out;
}

var size = glyphSize('a',{
  'font-family':'fantasy, sans-serif' // css to apply to the test element
});

/* size = {
 width:7,
 height:20
} */

修改:快速演示here

答案 1 :(得分:0)

看到你的问题并自己解决了问题。 在我看来,我解决了这个问题。 我刚刚创建了一个不透明度为0.0的新文本元素。 我将它添加到svg,获取bbox并将其删除。 bbox包含宽度和高度:

getBBox : function(svgId, text, styleClass) {
    // Add tmp text element to the SVG
    var tempSvgTextElement = d3.select("#" + svgId)
    .append("text")
    .style("opacity", 0.0)
    .attr("class", styleClass);

    var tSpanTextNode = document.createTextNode(text);
    var svgTSpan = tempSvgTextElement.append("tspan").attr("class", styleClass).node();
    svgTSpan.appendChild(tSpanTextNode);
    var bbox = tempSvgTextElement.node().getBBox();
    tempSvgTextElement.remove();
    return bbox;
}