Рассчитать точный размер шрифта глифа
Мне нужен способ найти точный размер и положение глифа относительно его ограничительной рамки.
Мы используем D3.js для создания SVG с заголовком, поменьше подписи и коротким основным текстом. В значительной степени это:
Lorem Ipsum
Lorem Ipsum Dolor
Лорем ипсум долор сит амет,
Концертёр по адептизингу элит,
sed do eiusmod tempor
Инцидент ут Лабор и Долоре
Великая Аликва
Как и в этом примере, мне нужно, чтобы текст был выровнен по левому краю независимо от размера шрифта.
Проблема в том, что ограничивается прямоугольник каждой строки, а не глифы. Что заставляет заголовки выглядеть с отступом. Как рассчитать расстояние между ограничительной рамкой и глифом, чтобы правильно выровнять текст?
Коллега сел и вручную измерил это для английского шрифта, который работает довольно хорошо. Возможно, мы могли бы сделать это в 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>
Это x
а также y
значения на text
а также tspan
элементы, которые мы должны рассчитать, отрицательные x
ценности в частности. Примечание: мы на самом деле не используем serif
или же sans-serif
семейства шрифтов, мы используем собственный шрифт. Я не думаю, что английский шрифт создан с учетом использования Интернета. Мы использовали http://www.fontsquirrel.com/ для создания файла шрифта SVG.
Обновить
SVG-шрифты казались наиболее логичным вариантом, поскольку у вас есть вся информация о пути в файле, читаемом на узле. Вам просто нужно это интерпретировать. Но мы нашли и решили воспользоваться opentype.js, который работает со шрифтами otf и ttf.
Я все еще хотел бы знать, возможно ли это вообще делать со шрифтами SVG.
2 ответа
Я думаю, что это может делать то, что вы хотите. Обратите внимание, что он требует jQuery и немного хакерский. Вы можете установить высоту строки в объекте css.
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
} */
редактировать: быстрое демо здесь
Увидел твой вопрос и сам столкнулся с проблемой. Я решил это очень просто, на мой взгляд. Я только что создал новый текстовый элемент с непрозрачностью 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;
}