SVG 文本 – text、tspan 和 textPath 元素

SVG 可以渲染三类主要图形内容:矢量形状、图像和文本。SVG text 不只是 canvas 上的普通字母。它可以用坐标定位,用 CSS 或 presentation attributes 设置样式,进行变换、裁剪,并沿 path 排列。本文解释文本如何在 SVG 标记中书写和布局。

本文将学习:

  • 使用 <text> 把 SVG 文本放在指定 baseline 位置。
  • 使用 <tspan> 创建多行 SVG 文本和 inline styling。
  • 使用 <textPath> 让文本沿 path curve 排列。
  • 控制文本对齐、方向、writing mode、textLength 和 glyph spacing。
  • 理解 characters、glyphs 和 fonts 的区别。

什么是 Glyphs、Fonts 和 Characters?

当你需要精确控制 SVG 文本渲染时,理解 characters、glyphs 和 fonts 的关系非常重要。

SVG Text Content Elements

SVG 定义三个生成可见文本的内容元素:

元素用途
<text>定义一段文本。
<tspan><text> 内提供细粒度定位和样式。
<textPath>沿 <path> 曲线排列文本。

如何向 SVG 添加文本

  1. <svg> 文档内创建 <text> 元素。
  2. 设置 xy 属性定位文本 baseline。
  3. 添加字体和绘制属性,例如 font-familyfont-sizefillstroke
  4. 当一个文本块需要多行或混合样式时,使用 <tspan> 元素。
  5. 当文本必须沿 path 而不是直线 baseline 排列时,使用 <textPath>
  6. 如果文本被裁剪,检查 viewport、baseline 和 font size。

SVG <text> 元素

<text> 元素创建一段文本。xy 属性定位文本 baseline 的起点,而不是文本框的左上角。由于 baseline 位于字母底部附近,较小的 y 值可能让部分文本落在 viewport 上方。实际使用时,应根据所选 font-size 设置足够大的 y 值。

下面的示例展示为什么 baseline 位置很重要。第一段文本使用很小的 y 值,因此字母被裁剪;第二段文本把 baseline 下移后完全可见( svg-text-position.svg)。

1<svg height="100" width="200" xmlns="http://www.w3.org/2000/svg">
2    <text x="10" y="6" fill="red">The text is not fully visible </text>
3    <text x="10" y="30" fill="green">The text is fully visible </text>
4</svg>

SVG 文本 baseline 定位示例,展示被裁剪和可见文本

<text><tspan> 的属性控制书写方向、对齐、字体、间距和字符定位。最常用的属性包括:

这些属性可以组合出复杂布局,例如拉伸文本、从右到左脚本或垂直书写。

1<svg height="300" width="400" xmlns="http://www.w3.org/2000/svg">
2    <text x="180" y="30" fill="red">Aspose.SVG</text>
3    <text x="180" y="60" fill="blue" textLength="140">Aspose.SVG</text>
4    <text x="180" y="90" fill="grey" textLength="160" lengthAdjust="spacingAndGlyphs"
5          style="direction: rtl; unicode-bidi: bidi-override">Aspose.SVG</text>
6    <text x="180" y="120" fill="green" style="text-anchor: middle">Aspose.SVG</text>
7    <text x="260" y="90" style="writing-mode: tb">Aspose.SVG</text>
8</svg>

SVG 文本排列示例,展示 textLength、text-anchor、从右到左方向和垂直书写

<tspan> – Inline Styling 和换行

<tspan> 可以嵌套在 <text> 或另一个 <tspan> 内。作为子元素,<tspan> 在文本显示和格式化中有两个重要作用:

  1. SVG 文本不会自动换行。使用 <tspan> 元素创建独立行,并给每一行自己的位置。
  2. 当文本块中只有一部分需要不同样式、位置、颜色、字号或字重时,使用 <tspan>
1<svg height="300" width="600" xmlns="http://www.w3.org/2000/svg">
2    <text x="20" y="60" style="font-family:arial">
3        <tspan style="font-weight:bold; font-size:55px">ASPOSE</tspan>
4        <tspan x="50" y="90" style="font-size:20px; fill:grey">Your File Format APIs </tspan>
5    </text>
6</svg>

SVG tspan 示例,展示不同字号和 fill 颜色的多行文本

SVG <textPath> – 沿曲线排列文本

<textPath> 把文本附着到 <path> 元素,使字符沿任意矢量曲线排列。path 可以通过两种方式引用:

 1<svg height="300" width="800" xmlns="http://www.w3.org/2000/svg">
 2    <path id="my_path1" d="M 50 100 Q 25 10 180 100 T 350 100 T 520 100 T 690 100"
 3          fill="transparent" />
 4    <path id="my_path2" d="M 50 100 Q 25 10 180 100 T 350 100"
 5          transform="translate(0,75)" fill="transparent" />
 6    <text>
 7        <textPath href="#my_path1">
 8            Aspose.SVG for .NET is a flexible library for SVG file processing and is fully compatible with its specifications.
 9        </textPath>
10        <textPath href="#my_path2">
11            Aspose.SVG for .NET is a flexible library for SVG file processing and is fully compatible with its specifications.
12        </textPath>
13    </text>
14</svg>

SVG textPath 示例,展示文本沿两条曲线路径排列

如果 path 短于文本,溢出部分会在 path 末端被裁剪。样式设置与普通文本相同:可以应用 font-weightfont-styletext-decorationtext-transform 等 CSS properties。

图中两段文本分别附着在两条不同 paths 上。第一行沿较长的波浪路径排列,第二行因为引用的 path 较短而更早停止。

Common Mistakes and Fixes

问题原因解决方法
文本在 viewport 顶部被裁剪y 值小于 font sizey 设置得大于 font size,例如 24 px 文本可用 y="30"
文本没有按预期沿曲线排列href 指向不存在的 <path> ID检查 <path>id,确保 href 值完全匹配
Glyphs 看起来变形使用 textLengthlengthAdjust 设置为 spacing使用 lengthAdjust="spacingAndGlyphs" 同时缩放 spacing 和 glyphs
从右到左文本仍按从左到右显示缺少 unicode-bidi:bidi-override<text><tspan> 上添加 style="direction: rtl; unicode-bidi: bidi-override"
文本没有换到新行依赖自动换行为每一行插入带独立 x/y 坐标的新 <tspan>

Quick Recipes

目标SVG 片段
水平居中文本<text x="50%" y="50%" text-anchor="middle" dominant-baseline="middle">Centered</text>
垂直文本<text x="20" y="20" writing-mode="tb">Vertical</text>
将文本拉伸到指定宽度<text x="10" y="40" textLength="200" lengthAdjust="spacingAndGlyphs">Stretch me</text>
把文本放到曲线上<path id="curve" d="M10,80 C40,10 65,10 95,80" fill="none"/> <text><textPath href="#curve">On a curve</textPath></text>
应用下划线和上划线<text x="10" y="40" style="text-decoration: underline overline;">Styled</text>

FAQ – SVG 文本

如何定位 SVG 文本?

<text> 元素上设置 xy 属性。y 值定位 baseline,因此通常需要大于 font size,避免文本在 viewport 顶部被裁剪。

如何创建多行 SVG 文本?

在一个 <text> 元素中使用多个 <tspan> 元素。给每一行自己的 xy 值,或使用 dy 让每一行相对于上一行移动。

SVG 文本可以沿曲线排列吗?

可以。定义带 id<path>,然后在 <textPath href="#path-id"> 中引用它。文本会沿 path geometry 排列,并仍可使用文本相关 CSS properties 设置样式。

可以把 SVG 文本转换成矢量轮廓吗?

可以。当需要不依赖字体的输出时,可以把文本转换为 vector paths。参见 Text Vectorization & Text Security – .NETConvert SVG Text to Vector in Python

规范和相关资源

Text to Vector 应用横幅