我希望创造一个文本效果,在其中的文本线自动缩放,以达到一个特定定义的宽度,与自动调整高度。
理想情况下,我可以将多个单词堆叠在一起,以实现与下面类似的视觉效果。
示例图像
对于SVG文本来说,这是可能的吗?它能通过纯CSS来完成吗?
发布于 2022-08-16 18:40:16
很可能,您应该包括一些javaScript以获得所需的结果。
主要问题:
svg <text>
元素没有类似于多行文本或行高的任何东西。因此,您需要将文本内容拆分为许多具有不同<tspan>
偏移量的y
元素,以模拟类似于HTML的内容。
此外,许多重要的属性还不能用css进行样式处理。最重要的是,x
和y
是模拟直线高度的关键。
示例:模拟多行svg文本缩放字体大小到宽度
let svg = document.querySelector('svg')
let svgPseudoP = document.querySelector('.svgPseudoP');
svgSplitTextLines(svgPseudoP)
//split newlines
function svgSplitTextLines(el) {
let texts = el.querySelectorAll('text');
for (let t = 0; t < texts.length; t++) {
let text0 = texts[t];
let [x0, y0] = [text0.getAttribute('x'), text0.getAttribute('y')];
//trim empty elements and whitespace
let lines = text0.innerHTML.split(/\r?\n/);
lines = lines.map((str) => {
return str.trim()
}).filter(Boolean)
//set first line as textContent
text0.textContent = lines[0];
// calculate proportions
let width0 = text0.getComputedTextLength();
let style0 = window.getComputedStyle(text0);
let fontSize0 = parseFloat(style0.getPropertyValue('font-size'));
// ratio between capital letter height and font size
let ascenderRatio = 0.71582;
// define ideal leading
let leading = fontSize0 * 0.2;
for (let i = 1; i < lines.length; i++) {
let str = lines[i];
let tspan = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');
tspan.textContent = str;
tspan.setAttribute('x', x0);
text0.appendChild(tspan);
// scale font size according to width
let width = tspan.getComputedTextLength();
let scale = width0 / width;
let newFontSize = parseFloat(fontSize0) * scale;
tspan.setAttribute('style', 'font-size:' + newFontSize + 'px');
// emulate line height by increasing Y offset
let tspanPrev = tspan.previousElementSibling;
let yPrev = tspanPrev ? +tspanPrev.getAttribute('y') : +text0.getAttribute('y');
let newY = yPrev + (newFontSize * ascenderRatio)
tspan.setAttribute('y', newY + leading);
}
}
}
svg {
width: 50%;
border: 1px solid #ccc;
}
text {
font-family: Arial;
font-weight: bold;
text-anchor: middle;
text-transform: uppercase;
}
<svg class="svgPseudoP" viewBox="0 0 100 100">
<text x="50%" y="20" font-size="10">
Example
Text
Goes here
</text>
<text x="25%" y="60" font-size="8">
Example2
Text
Goes
here
</text>
</svg>
本质上需要以下步骤:
text.getComputedTextLength()
let scale = widthIdeal / widthCurrentLine;
let newFontSize = fontSizeFirst * scale
这将需要获得大写字母高度与字体em正方形之间的比率,否则字体大小较大的行将比较小的行增加更大的边距。
例如,在inkscape、Illustrator等的100个点用Arial写一个大写,并将其转换为路径/轮廓,并检查它的高度: 71.582 pt
因此,资本与经济的平方比是:100/71.582 = 0.71582
这个值取决于实际的字体文件度量,因此没有标准化的大写字母高度。但是,对于许多字体家族来说,0.72-0.75的比值应该是可以接受的。
的例子:不均衡导致由于不理想的资本对em平方比。
上面的示例代码还将基于标记的新行拆分为<tspan>
元素:
<text x="50%" y="20" font-size="10">
Example
Text
Goes here
</text>
将改为:
<text x="50%" y="20" font-size="10">
Example
<tspan x="50%" style="font-size:18.9px" y="35.5">Text</tspan>
<tspan x="50%" style="font-size:8.1px" y="43.3">Goes here</tspan>
</text>
https://stackoverflow.com/questions/73373975
复制相似问题