前置知识: HTML5

SVG 概述:图标放大三倍也不糊的秘密

7 min入门

以「图标放大三倍不糊」引入,讲清 SVG 用文本描述矢量的本质、位图与矢量的放大对照实验、主战场与三种嵌入方式预告,零工具起步。

前置知识

  • 已完成 HTML5 概述:知道网页里 <img> 怎么用。不需要任何设计软件——本模块全程用文本编辑器与浏览器。

学习目标

读完本文你将能够:

  1. 说清 SVG「用文本描述形状」的本质,以及它与 PNG 位图的放大差异根源;
  2. 完成零工具起步:写一个最小的 .svg 文件并在浏览器打开;
  3. 对「图标用 SVG 还是 PNG」给出有依据的选择;
  4. 说出三种嵌入网页方式的存在与分工预告。

预计 30 到 45 分钟。

1. 你现在要解决什么问题

把一张 PNG 图标放大三倍,边缘出现锯齿;把同一个图标换成 SVG,任意缩放都锐利。原因一句话:PNG 存的是「每个像素什么颜色」的快照,SVG 存的是「怎么画出这个形状」的说明书。快照放大就是糊,说明书放大重画一遍即可。今天所有主流网站的图标、插画、图表,都在换用这纸说明书。

2. 最小可运行示例:六行的第一个 SVG

新建 first.svg,内容:

plaintext
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="100">
  <rect x="10" y="10" width="80" height="80" fill="#39C5BB" />
  <circle cx="140" cy="50" r="30" fill="#FF6699" />
</svg>

把这个文件直接拖进浏览器(或双击用浏览器打开)。预期效果:浅蓝色圆角方形(左)与一枚粉色圆形(右)并排,放大页面(Ctrl+加号)到 400%——边缘依旧锐利。这就是矢量承诺的现场版:浏览器在每次渲染时按「说明书」重新计算形状。

对照实验:把同样的两个形状截图保存为 png,放大 400% 观察锯齿。两图并排一贴,本文的核心就懂了。

3. 发生了什么:SVG 是一门 XML 小语言

.svg 文件是纯文本——用记事本就能打开编辑。<svg> 是画布,<rect>、<circle> 是形状指令,fill 是属性。它遵守 XML 语法:标签必须闭合、属性必须带引号——这也是调试的抓手:XML 语法错了,浏览器直接整幅空白(020 篇展开排查)。

三个推论:

  1. 文本即图片:可以用 Git 管理版本、可以程序化生成(图表库的本质)、可以在 CSS/JS 里改颜色;
  2. 无损无限缩放:尺寸信息与形状分离(030 篇的 viewBox 就是分离的关键字);
  3. 体积与复杂度成正比:一张照片的「说明书」会大到离谱——照片永远归位图。

4. 核心概念:SVG 与位图/Canvas 的选型

维度SVGPNG/JPG(位图)Canvas
本质形状说明书像素快照JS 实时绘制的画板
放大无损锐利锯齿视像素密度
适合图标、插画、图表、UI 装饰照片、复杂纹理高频重绘的游戏/可视化
DOM 可交互是(每个形状都是元素)否否(像素)

一句话选型:要缩放与交互选 SVG,是照片选位图,要每帧重绘选 Canvas。本仓库 FANDEX 站点 itself 的「轨道星系」装饰就是 SVG 的主场。

5. 调试实录:白屏排查

改了 first.svg 刷新浏览器却毫无变化。两步定位:

  1. 确认改的是浏览器打开的那份:地址栏路径与编辑器保存路径核对(file:// 路径拼写错一个字符,浏览器会展示旧缓存或 404 空白);
  2. 确认 XML 仍合法:去掉任何一个标签的右尖括号,浏览器给出空页——XML 严格语法下「错一半」等于「全错」,逐标签回滚到上一次正确版本再改。

(html5 模块的 net::ERR_FILE_NOT_FOUND 排查法在此同样适用:路径大小写敏感。)

6. 修改实验

  1. 把 circle 的 cx 从 140 改成 60,预测两个形状的位置关系(重叠),验证;
  2. 给 rect 加属性 rx="10",观察圆角出现——这是图标圆角的来源;
  3. 把 width/height 同时乘 2,形状锐利依旧——亲手兑现「无损缩放」。

7. 小练习

预测题:<rect x="10" y="10" width="80" height="80" /> 与 <circle cx="50" cy="50" r="40" /> 谁在视觉上更靠左?写出两者最左边缘的横坐标。

修改题:新增第三个形状 polygon points="100,90 130,10 160,90"(三角形),并给三兄弟各换一种 fill 颜色。

修 Bug 题:同事发来的 svg 打开是空白,内容只有一行 <svg width=100 height=100><rect .../></svg>——找出两处语法问题(缺 xmlns、属性值缺引号)。

挑战题(不看提示):手写一枚「对话气泡」图标(圆角矩形 + 一个小三角形尾巴),文件不超过 10 行,尺寸 48x48,浏览器里放大 300% 验证锐利。

先自己动手或写下预测,再展开参考答案对照:

参考答案(先自己写,再展开对照)

预测题:rect 更靠左。rect 最左边缘横坐标是 x = 10;circle 的最左点是 cx - r = 50 - 40 = 10。两者最左边缘其实同为 10——但 circle 顶部与底部的横坐标都向内收(圆的特性),视觉重心更靠中,所以「看起来」rect 更靠左。这道题的真正考点:圆形没有「左边一整条边」,判断边界要用 cx ± r 推算,这是后面所有形状对齐的基本功。

修改题参考:

plaintext
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="100">
  <rect x="10" y="10" width="80" height="80" fill="#39C5BB" />
  <circle cx="140" cy="50" r="30" fill="#FF6699" />
  <polygon points="100,90 130,10 160,90" fill="#66CC99" />
</svg>

验证点:polygon 的 points 是「x,y 空格分隔」的顶点序列,三个顶点首尾自动相连闭合。

修 Bug 题:两处问题——缺 xmlns="http://www.w3.org/2000/svg"(独立 .svg 文件是 XML,缺名字空间整幅白屏);width=100 height=100 属性值没加引号(XML 语法要求属性必须带引号,HTML 的宽容不适用于 .svg 文件)。修正后:<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">。

挑战题参考(10 行内,形状可自由发挥):

plaintext
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 48 48">
  <rect x="6" y="8" width="36" height="26" rx="8" fill="#39C5BB" />
  <polygon points="14,32 22,32 12,42" fill="#39C5BB" />
</svg>

要点核对:rect 的 rx=“8” 给出气泡的圆角;三角形尾巴的两个上顶点 (14,32) 与 (22,32) 落在矩形底边上,视觉上与矩形连成一体;同色填充让接缝不可见。放大 300% 边缘依旧锐利——又一次亲手验证「说明书放大重画」。

8. 什么时候应该 / 不应该用 SVG

应该:UI 图标与 logo(多尺寸适配)、插画与信息图、需要随主题换色的装饰(fill 可由 CSS 控制)、可访问性要求高的图形(文本可被读屏)。

不应该:照片与复杂渐变纹理(体积爆炸);需要逐像素处理的特效(Canvas 更合适);作为超大背景图(浏览器的栅格化开销要预算)。

9. 与之前和之后的知识的关系

  • 往前:html5 模块的 <img> 是消费图片的默认方式,svg 给了你「自己生产图片」的能力;inline SVG 嵌入后每个形状可被 JS 操作(与 410 篇 DOM 知识接轨);
  • 往后:020 篇补齐文档结构(defs 复用与分组),030 篇的 viewBox 是「响应式图标」的钥匙;css 模块的 fill 控制与 Tailwind 类尺寸工具是图标工程的下半场。
  • 更远:图表库(ECharts/D3)输出的全是 SVG——本模块是数据可视化的地基。

10. 官方文档

11. 自我检查

  • 能说清 SVG 与位图的存储差异及放大表现差异的根源;
  • 能零工具写出六行的 .svg 并在浏览器打开验证;
  • 能对图标/照片/游戏三个场景各选对技术并给出理由;
  • 已完成三个修改实验。

本章总结

SVG 用文本描述形状:文本即版本、缩放即重画、形状即元素。位图存快照、Canvas 是画板,三者选型的分母是「要不要缩放与交互」。下一页把画布的语法骨架搭起来。

下一步

进入 SVG 基础语法与文档结构:六行之外的完整骨架。