问题
I need a way to find the exact size and position of a glyph relative to its bounding box.
We're using D3.js to create an SVG with a heading, a smaller byline and a short body text. Pretty much this:
Lorem ipsum
Lorem ipsum dolor
Lorem ipsum dolor sit amet,
consectetur adipisicing elit,
sed do eiusmod tempor
incididunt ut labore et dolore
magna aliqua
As in this example, I need the text to be left-aligned regardless of font-size.
The problem is that it is each lines bounding box that's aligned and not the glyphs. Which makes the headings look indented. How can I calculate that space between the bounding box and the glyph so I can correctly align the text?
A colleague sat down and manually measured this for the English font, which works pretty well. We could probably do this in Adobe Illustrator, but we need the information for English, Chinese and Arabic fonts. To do this by hand is more or less impossible.
The only solution I can come up with is to type each character in a canvas element and map each pixel to see where the glyph starts and ends.
What I think would be ideal is a way to use the SVG font path information to find the extremes, that way we would get the exact numbers instead of estimates. Our estimates have a big margin of error. Is there a way to do that with node.js?
An example of what the SVG looks like:
<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>
It is the x
and y
values on the text
and tspan
elements we need to calculate, the negative x
values in particular. Note: we don't actually use the serif
or sans-serif
font families, we use a custom font. I don't think the English font is created with web use in mind. We used fontsquirrel.com to create the SVG font file.
Update
SVG fonts seemed like the most logical option, since you have all the path information in the file readable in node. You'd just have to interpret it. But we found, and decided to go with, opentype.js which works with otf and ttf fonts.
I'd still like to know if this is at all possible to do with SVG fonts.
回答1:
I think this may do what you want. Note that it requires jQuery and is a bit hacky. You may want to set line-height in the css object.
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
} */
edit: quick demo here
回答2:
Saw your question and had the problem myself. I solved it very simple in my opinion. I just created a new text element with opacity 0.0. I add it to the svg, get the bbox and remove it. The bbox contains the width and height:
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;
}
来源:https://stackoverflow.com/questions/24325731/calculate-the-exact-size-of-a-font-glyph