SVG-动态创建textpath的路径吗?

时间:2019-01-14 07:11:55

标签: svg text

我想在SVG中沿路径(半圆)弯曲文本。我已经阅读了本教程,该教程很棒:https://css-tricks.com/snippets/svg/curved-text-along-path/

问题在于,此处显示的路径仅适用于此特定文本-Dangerous Curves Ahead。如果仅留下Dangerous个单词,则会发生以下情况:https://codepen.io/anon/pen/pqqVGa-它不再起作用(文本不再均匀地分布在路径上)。

无论文本长度如何,我都希望它能正常工作。如何实现?

2 个答案:

答案 0 :(得分:2)

这是假定初始文本大小(35)太小。

let curveLength = curve.getTotalLength();
let fs = 35;//the initial font size
test.setAttributeNS(null, "style", `font-size:${fs}px`)
while(test.getComputedTextLength() < curveLength){
  fs++
  test.setAttributeNS(null, "style", `font-size:${fs}px`)
}
body {
  background-color: #333;
}

text {
  fill: #FF9800;
}
<svg viewBox="0 0 500 500">
    <path id="curve" d="M73.2,148.6c4-6.1,65.5-96.8,178.6-95.6c111.3,1.2,170.8,90.3,175.1,97" />
    <text id="test">
      <textPath xlink:href="#curve">
        Dangerous
      </textPath>
      </text>
  </svg>

更新

OP正在评论:

  

感谢您的回复。我宁愿创建一个更长/更小且与文本宽度匹配的新路径,而不是调整字体大小。不知道如何做到这一点。 – feerlay

请阅读代码中的注释。根据文本的长度,我正在计算新路径,但是我假设了很多事情:我假设新路径在与旧路径相同的位置开始。

let textLength = test.getComputedTextLength();
// the center of the black circle
let c = {x:250,y:266}
// radius of the black circle
let r = 211;
// the black arc starts at point p1
let p1 = {x:73.2,y:150}
// the black arc ends at point p2
let p2 = {x:426.8,y:150}
// distance between p1 and p2
let d = dist(p1, p2);
// the angle of the are begining at p1 and ending at p2
let angle = Math.asin(.5*d/r);

// the radius of the new circle
let newR = textLength / angle; 
// the distance between p1 and the new p2
let newD = 2 * Math.sin(angle/2) * newR;
// the new attribute c for the path #curve
let D = `M${p1.x},${p1.y} A`
D += `${newR}, ${newR} 0 0 1 ${p1.x + newD},${p1.y} `
document.querySelector("#curve").setAttributeNS(null,"d",D);
// a function to calculate the distance between two points
function dist(p1, p2) {
  let dx = p2.x - p1.x;
  let dy = p2.y - p1.y;
  return Math.sqrt(dx * dx + dy * dy);
}
body {
  background-color: #333;
}

text {
  fill: #FF9800;
}; 
<svg viewBox="0 0 500 500">
    <path id="black_circle" d="M73.2,148.6c4-6.1,65.5-96.8,178.6-95.6c111.3,1.2,170.8,90.3,175.1,97" />
  
  <path id ="curve"  d="M73.2,150 A 211,211 0 0 1 426.8,150" fill="#777" />
    <text id="test">
      <textPath xlink:href="#curve">
        Dangerous curves
      </textPath>
      </text>

  
  </svg>

答案 1 :(得分:2)

使用属性lengthAdjusttextLength,您可以调整文本的长度和字母的高度,从而将所需长度的文本放置在固定长度的段上

<svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg" 
    xmlns:xlink="http://www.w3.org/1999/xlink"  width="500" height="300" viewBox="0 0 500 300">  

<path id="path1" fill="none" stroke="black" d="M30,151 Q215,21 443,152 " /> 

<text id="txt1" lengthAdjust="spacingAndGlyphs" textLength="400" font-size="24">
<textPath id="result" method="align" spacing="auto" startOffset="1%" xlink:href="#path1">
<tspan dy="-10"> very long text very long text very long text </tspan>

</textPath>
</text>
	
</svg>

使用属性startOffset =" 10% ",您可以调整词组第一个字符的位置

<svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg" 
    xmlns:xlink="http://www.w3.org/1999/xlink"  width="500" height="300" viewBox="0 0 500 300" >  

<path id="path1" fill="none" stroke="black" d="M30,151 Q215,21 443,152 " /> 

<text id="txt1" lengthAdjust="spacingAndGlyphs" textLength="400" font-size="24">
<textPath id="result" method="align" spacing="auto" startOffset="15%" xlink:href="#path1">
<tspan dy="-10"> very long text very long text very long text </tspan>

</textPath>
</text>
	
</svg>
 

并使用此属性制作动画(单击画布

<svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg" 
    xmlns:xlink="http://www.w3.org/1999/xlink"  width="500" height="300" viewBox="0 0 500 300">  

<path id="path1" fill="none" stroke="black" d="M30,151 Q215,21 443,152 " /> 

<text id="txt1" lengthAdjust="spacingAndGlyphs" textLength="200" font-size="24">
 <textPath id="result" method="align" spacing="auto" startOffset="-100%" xlink:href="#path1">
    <tspan dy="-10"> Very long text Very long text Very long text </tspan>
  <animate
   begin="svg1.click"
   dur="15s"
   attributeName="startOffset"
   values="-100%;1%;1%;100%;1%;1%;-100%"
   repeatCount="5"/> 
 </textPath>
</text>
 
  <text x="200" y="150" font-size="24" fill="orange" >Click me </text>
	
</svg>