跳到主要内容

形状文字与图像

基本形状是语法糖;text 不是排版引擎;image 是带 CORS 的替换元素。不要按 MDN 标签清单逐个背,按「要不要进编辑器几何」「要不要 IME」「要不要导出像素」选。

1. 基本形状何时换成 path

rect / circle / ellipse / line / polyline / polygon 适合静态图标和「永远是这种形状」的控件。换成 path 的时机:

  • getPointAtLength、等距采样、箭头,见 路径几何与测量
  • 要节点编辑、布尔运算、钢笔工具——clip 不能当布尔,见 clipPath-mask 与 marker
  • 要和自由曲线进同一套命中 / 序列化。

不适用:为了「统一」把所有 icon 打成 path,文件变大,圆角 rx 反而丢失语义。可编辑文档存作者意图(仍是 circle),渲染/测长再派生 d

lineobjectBoundingBox 宽或高为 0,渐变和部分滤镜会静默失败,见 渐变 Pattern 与滤镜。装饰线要么 userSpaceOnUse,要么换成有厚度的 path

2. text / tspan 不自动折行

SVG 文字是 锚定的字形游标,不是 CSS 块盒。没有宽度就不会折行。tspan 只换样式或手动给新的 x/y/dx/dy

export function setSingleLineText(
textEl: SVGTextElement,
content: string,
x: number,
y: number,
): void {
textEl.setAttribute("x", String(x));
textEl.setAttribute("y", String(y));
textEl.textContent = content;
}

多行:自己按度量拆成多个 tspan(每行一个 y),或放弃 SVG 文字。

需求做法
图标旁一句标签<text>text-anchor / dominant-baseline
可编辑段落、IME、选区HTML overlay,见 Overlay 与 HTML 叠加
必须跟相机缩放的短表单foreignObject,见 foreignObject

SVG 2 的 inline-size 自动折行 不要当生产默认,实现差、排版与 CSS 不一致。textLength + lengthAdjust 是压缩/拉伸已有字形,不是折行。

getBBox 对文字返回墨水近似盒,基线、悬挂标点、字体未加载时会跳。字体要 document.fonts.load 后再量。命中热区不要只信文字盒,给透明 rect 或用 pointer-events

3. imagehref 与 CORS

新代码用 href(或 CSS xlink 已过时的等价物)。xlink:href 只为读老文件而解析,不要再写

export function setSvgImage(
image: SVGImageElement,
href: string,
cors: "anonymous" | "use-credentials" | null,
): void {
image.setAttribute("href", href);
if (cors) {
image.setAttribute("crossorigin", cors);
} else {
image.removeAttribute("crossorigin");
}
}

跨域图不带 CORS 时:能画,但后续 canvas.drawImage(svg) / 光栅导出可能污染,见 08 安全preserveAspectRatioimage 上独立于外层 <svg>,切片对不齐通常是子元素自己的 meet/slice 错了。

width/height 必须显式。缺尺寸时引擎行为分裂,有的是 0、有的是 intrinsic。不要指望它像 HTML img 那样把布局撑开。

4. currentColor

fill="currentColor" / stroke="currentColor" 吃的是元素的 CSS color(可继承)。图标 sprite、按钮内联 SVG 用它换主题,避免每个 path 写死 #333

它不是 CSS 变量替代品:设计 token 仍用 var(--icon) 更合适。currentColor 适合「跟周围文字走」。color 写在 <g> 或宿主 HTML 上即可,不必每个叶子写一遍。

5. 失败形态

症状原因
长标题画出 viewBox以为 text 会按宽度折行
中文输入候选框飞掉在 SVG text 里自造 caret,没用 HTML
图是空白矩形image 没有 width/height,或 href 写成了 xlink:href 且没 NS
导出 PNG 失败跨域 image 未 CORS
直线上的渐变消失objectBoundingBox + 零尺寸盒

权威资料

核对日期:2026-08-26