如何使用tspan元素给SVG文本添加样式、定位

发布于 彦子

SVG的<text>元素允许你很简单地定位和给文本添加样式,但是如果你想要针对文本的不同部分定位和添加样式呢?难道我们要去创建多个text元素吗?不需要的。有更简单的方式,tspan来拯救世界了。

前两周我们已经看了SVGtext元素,并整理了几个我们可以使用的属性

<text>元素不是唯一的SVG文本显示的方式。今天我们来讨论另外两种可以结合<text>元素使用的SVG元素——<tspan><tref>

tspan元素

你可以把<tspan>元素当成SVG文本span。你可以用<tspan>来包裹SVG文本,来对它们做整体控制,关于显示和定位,文本片段之间的相互关系等。

我们从一个简单的示例开始。

<svg width="660" height="220" style="outline: 1px solid red; font-size: 2em; overflow: visible;">  
  <text x="240" y="120">  
    <tspan>SVG</tspan>  
    <tspan>SVG</tspan>  
  </text>  
</svg>

这里大多数的代码对你来说应该是熟悉的,在阅读了前面两篇文章之后。我创建了一个<svg>元素,定义了SVG视窗的尺寸,添加了一个红色的边框,这样我们可以看到它的边界。我还把font-size设置为2em,以及overflow: visible;,这样我们可以看到视窗之外的内容。

我在(240,120)的位置放置了一个text元素,里边有两个tspan,每个都包含了内容为SVG的文本。效果如下:

SVG SVG

tspan中的文本按照内联顺序排列,和它们直接在text元素中显示的一样,中间有个空格。

有一点非常有趣的是,可以给<text>元素添加的属性也都可以添加给<tspan>元素。

我们来改变一下第二个tspan的位置,通过设置xy坐标。这样我们可以把两个tspan分开。

<svg width="660" height="220" style="outline: 1px solid red; font-size: 2em; overflow: visible;">  
  <text x="240" y="120">  
    <tspan>SVG 1</tspan>  
    <tspan x="10" y="10">SVG 2</tspan>  
  </text>  
</svg>

我把第二个tspan移到了(10,10)的位置。因为xy都是绝对定位,SVG 2的位置就移到了视窗的左边缘,也就是上边缘的下方。

SVG 1SVG 2

你可能记得上一篇文章中我们提到了y坐标表示的是基线的位置,不是文本的顶部或底部,而是在中间的一个位置。

为了相对定位,我们可以在下面的实例中使用dxdy来定位。

<svg width="660" height="220" style="outline: 1px solid red; font-size: 2em; overflow: visible;">  
  <text x="240" y="120">  
    <tspan>SVG 1</tspan>  
    <tspan dx="50,10,10,0,5" dy="50,10,10,10">SVG 2</tspan>  
  </text>  
</svg>

这里我在第二个tspan中使用了dy坐标列,这样每个字符都是相对于前一个字符定位的。

SVG 1SVG 2

对于上面的第一个字符“S”,如果没有给定dxdy,那就是相对整个文本的位置定位的。

因为每个tspan都是单独的元素,除了定位之外,你还可以在给tspan里面的文本添加样式。

<svg width="660" height="220" style="outline: 1px solid red; font-size: 2em; overflow: visible;">  
  <text x="240" y="120">  
    <tspan>SVG 1</tspan>  
    <tspan dx="50,10,10,0,5" dy="50,10,10,10" fill="red">SVG 2</tspan>  
  </text>  
</svg>

这里我给SVG 2添加了一个红色的填充,默认填充是黑色。把它当成一个普通的span,唯一的不同就是它只能在<text>元素中使用。

SVG 1SVG 2

你可以直接在另一个tspan下方放置另一个tspan,通过给它们相同的x值,然后给第二个tspan一个dy值。

<svg width="660" height="220" style="outline: 1px solid red; font-size: 2em; overflow: visible;">  
  <text x="280" y="80">  
    <tspan>SVG 1</tspan>  
    <tspan x="280" dy="24" fill="red">SVG 2</tspan>  
  </text>  
</svg>

这里我设置的第二个tspanx属性值和text元素相同,然后再设置了24dy值,这样它就显示在第一个tspan下方了。

**注意:**除了dy,也可以使用y来进行设置。

SVG 1SVG 2

我们上周看的所有可以应用于text的属性都可以用于tspan。但是,有一件需要注意的事情是,所有设置给text元素的属性都会传播到tspan元素中。

<svg width="660" height="220" style="outline: 1px solid red; font-size: 2em; overflow: visible;">  
  <text x="280" y="80" rotate="10">  
    <tspan>SVG 1</tspan>  
    <tspan x="280" dy="36" fill="red">SVG 2</tspan>  
  </text>  
</svg>

这里我把text元素旋转了10度,你可以看到所有tspan中的内容也都旋转了10度,但是我没有明确地给tspan设置旋转。

SVG 1SVG 2

这并不奇怪,如果你想让第一个tspan的内容正常显示,不要额外给它设置旋转-10。如果设置了就会变成下面这样。

<svg width="660" height="220" style="outline: 1px solid red; font-size: 2em; overflow: visible;">  
  <text x="280" y="80" rotate="10">  
    <tspan rotate="-10">SVG 1</tspan>  
    <tspan x="280" dy="36" fill="red">SVG 2</tspan>  
  </text>  
</svg>

tspanrotate属性,会覆盖掉我们原来给text设置的rotate

SVG 1SVG 2

如果你想让它正常直立起来,直接给tspan设置rotate="0"即可。

<svg width="660" height="220" style="outline: 1px solid red; font-size: 2em; overflow: visible;">  
  <text x="280" y="80" rotate="10">  
    <tspan rotate="0">SVG 1</tspan>  
    <tspan x="280" dy="36" fill="red">SVG 2</tspan>  
  </text>  
</svg>

这样第一个tspan的内容就直立了。

SVG 1SVG 2

还有几个我们将要学习的属性,还有tref元素,但是我们今天先讲到这里。

总结

SVG的tspan元素,功能上类似于普通的HTMLspan元素。通过包裹成一个tspan,你可以对这部分文本进行操作,添加样式、定位,它和其它文本是独立开来的。

所有text元素可用的属性,tspan也都可以用,如fillstroke,还有很多其它的属性。

所有你给text元素应用的属性,都会传播到tspan元素中。如果你不希望继承某个属性值,你可以在tspan中给它设置新的值,覆盖掉原来text元素中的值。

下周,我会继续讲讲textLengthlengthAdjust属性的内容,然后会介绍<tref>元素,它可以帮助我们在重用SVG文本,跨不同的texttspan元素。

本文根据@Steven Bradley的《How To Style and Position SVG Text With The tspan Element》所译,整个译文带有我们自己的理解与思想,如果译得不好或有不对之处还请同行朋友指点。如需转载此译文,需注明英文出处:http://vanseodesign.com/web-design/svg-text-tspan-element/

彦子

在校学生,本科计算机专业。逗比一枚,热爱前端热爱生活,喜欢CSS喜欢JavaScript喜欢SVG,爱玩PS玩AI玩啊逗比的软件。努力向上,厚积薄发。

如需转载,烦请注明出处:https://www.fedev.cn/svg/svg-text-tspan-element.htmlAir Force 1 High