写一次SVG代码,然后在多个地方重用,可以帮助你写出更多模块化的代码,而且它也有助于维护。通过tref
元素,SVG可以很方便地重用text
元素的内容。
上周我大概讲解了tspan
元素,并通过几个实例讲了如何使用它来单独给文本添加样式和定位。几个示例中都使用了位置属性——x
、y
、dx
和dy
,还提到了其它几个属性。
我们现在来讲讲剩下的两个属性,然后再讲讲使用tref
元素重用SVG文本。不过注意tref
元素是SVG 1.1规范的一部分,它已经从SVG 2.0规范中删除了。我在这里介绍它,也许哪天你就碰到它了呢。
textLength
和lengthAdjust
属性
还有两个属性是textLength
和lengthAdjust
,这两个属性都可以直接添加给任何tspan
元素。
我们先创建一个SVG元素,定义视窗的尺寸,然后给它添加样式,这样我们可以看到视窗的边框以及渲染到视窗之外的内容,字号加大。
<svg width="660" height="220" style="outline: 1px solid red; font-size: 2em; overflow: visible;">
<text textLength="400" lengthAdjust="spacingAndGlyphs">
<tspan x="280" y="80">SVG 1</tspan>
<tspan x="280" dy="36" fill="red">SVG 2</tspan>
</text>
</svg>
我把两个tspan
上下放置,给第二个tspan
加一个红色填充。我还给<text>
元素添加了textLength
和lengthAdjust
属性。然而,文本没有拉伸。
但是,给第一个tspan
添加了这两个属性之后,它确实拉伸了间隔、还有字形,如下图所示。
<svg width="660" height="220" style="outline: 1px solid red; font-size: 2em; overflow: visible;">
<text x="280" y="40">
<tspan x="280" y="80" textLength="400" lengthAdjust="spacingAndGlyphs">SVG 1</tspan>
<tspan x="280" dy="36" fill="red">SVG 2</tspan>
</text>
</svg>
这是为什么呢?他们和rotate
属性不一样,给text
元素设置的textLength
和lengthAdjust
,不会扩散到tspan
。
这是一个例外,我发现如果你给text
元素添加textLength
和lengthAdjust
属性,然后没有给第一个tspan
设置x
和y
的值,那么textLength
和lengthAdjust
也有可能会被继承。
我不确定这是bug,还是预期的行为,但是我还是在这里提出来说一下,以防你之后碰到,然后纠结为什么。
<svg width="660" height="220" style="outline: 1px solid red; font-size: 2em; overflow: visible;">
<text x="280" y="80" textLength="400" lengthAdjust="spacingAndGlyphs">hello
<tspan>SVG 1</tspan>
<tspan x="280" dy="36" fill="red">SVG 2</tspan>
</text>
</svg>
在这个示例中我直接给text
元素添加了hello
文本,在第一个tspan
之前,我直接给text
元素添加了这两个属性。我还给text
元素加了定位,但是我没有给第一个tspan
添加任何x
和y
坐标,所以它定位在hello
文本之后。
hello
这个单词被拉伸了,因为它是text
中的内容,但是第一个tspan
中的内容“SVG 1”也被拉伸了。也就是说设置textLength
和lengthAdjust
会拉伸它们被应用的直线上(同一水平线),而不考虑它们是设置在哪个元素之上。
如果你把第二个tspan
元素的定位坐标删除,它也会成为被拉伸的元素之一,因为它也和前两个元素统一了战线。
不过我还是不确定这是否是预期的行为,或者是bug,或者是我写错了什么,在这里指出欢迎大家拍砖。
tref
元素
注意:tref
元素是SVG 1.1规范的内容,但是它已经从SVG 2.0规范中删除了。也就是说在你看到这篇文章的时候,可能它已经不工作了。所以这里使用图片来展示实例的结果
早在之前SVG系列的文章中,我说了可以在一个位置定义SVG代码,然后在SVG文件的其它部分重用。
tref
元素也是一样的。它允许你在一个<defs>
元素中定义引用文本,然后在后面引用它。如果你不了解<defs>
的话,我建议你回去看看之前的文章。
或者你可以看看我前面创建<text>
元素时候的示例,我在<defs>
标签中定义了<text>
元素。注意我给<text>
元素添加了一个id
,为referenced
。
当你想要显示文本的时候,在<tref>
元素中使用xlink:href
属性引用就可以啦。
<svg width="660" height="220" style="outline: 1px solid red; font-size: 2em; overflow: visible;">
<defs>
<text id="referenced">SVG 1</text>
</defs>
<text>
<tspan x="280" y="80">
<tref xlink:href="#referenced"/>
</tspan>
<tspan x="280" dy="36" fill="red">SVG 2</tspan>
</text>
</svg>
这里我在一个tref
元素中引用了“SVG 1”的文本,而“SVG 2”放置在一个tspan
中,放在“SVG 1”下面。
还有更高效的方法,设置defs
来包含文本“SVG”,然后在第二个和第二个tspan
中再额外加上数字1
、2
。
<svg width="660" height="220" style="outline: 1px solid red; font-size: 2em; overflow: visible;">
<defs>
<text id="referenced-2">SVG</text>
</defs>
<text>
<tspan x="280" y="80">
<tref xlink:href="#referenced-2"/> 1
</tspan>
<tspan x="280" dy="36" fill="red">
<tref xlink:href="#referenced-2"/> 2
</tspan>
</text>
</svg>
这里我在每个tspan
中加上了1
、2
,但是SVG这个文本就是作为一个引用放进去的。我还把id
改成了referenced-2
,这样它就不会和前面的示例混淆了。
在这些示例中,我把tref
放进了tspan
中,tref
还可以直接放在text
元素中。引用的文本可以出现在任何tref
元素出现的地方。
总结思考
如果你知道如何使用<defs>
,以及如何重用SVG代码。我想你学习<tref>
元素应该不会有任何困难的。
你可以在<defs>
标签中定义你想要重用的文本,然后在<tref>
元素中使用xlink:href
来引用文本。解释比较麻烦,直接使用比较容易理解。
关于SVG文本还有很多内容。接下来的两周,我将讲讲关于SVG支持的文本布局特性,以及向你展示一些可以在水平和垂直方向排列对齐SVG文本的属性。
本文根据@Steven Bradley的《How To Reuse SVG Text With The tref Element》所译,整个译文带有我们自己的理解与思想,如果译得不好或有不对之处还请同行朋友指点。如需转载此译文,需注明英文出处:http://vanseodesign.com/web-design/svg-text-tref-element/。
如需转载,烦请注明出处:http://www.w3cplus.com/svg/svg-text-tref-element.html