Skip to content

Canvas 与 SVG 的区别

Canvas 和 SVG 都是用于在网页上绘制图形的强大技术,但它们在工作原理、适用场景和特性上有本质区别。以下是它们的主要区别:

  1. 图形类型(核心区别)

    • SVG (Scalable Vector Graphics - 可缩放矢量图形):
      • 基于矢量。图形由数学公式定义的点、线、路径、形状(矩形、圆形等)、文本等元素组成。
      • 图形是对象,是文档对象模型的一部分。
      • 无限缩放不失真(因为是数学描述的)。
    • Canvas:
      • 基于位图光栅。它本质上是一个像素网格
      • 你通过 JavaScript API 在画布上绘制像素。绘制完成后,Canvas 不保留绘制的形状信息,只保留最终的像素数据。
      • 放大时会出现像素化(锯齿)。
  2. DOM 结构

    • SVG: SVG 元素是DOM 的一部分。每个图形(如 <circle>, <rect>, <path>)都是一个独立的 DOM 节点。你可以像操作其他 HTML 元素一样使用 JavaScript 和 CSS 来操作它们(添加事件、修改样式、动画)。
    • Canvas: Canvas 本身是一个 HTML 元素 (<canvas>),但它内部绘制的图形不是 DOM 的一部分。你无法直接通过 DOM 访问或操作画布上绘制的单个圆形或矩形。你只能操作 <canvas> 元素本身。
  3. 事件处理

    • SVG: 因为每个图形元素都是 DOM 节点,你可以直接给它们添加事件监听器(如 onclick, onmouseover),实现精细的交互(点击一个特定图形触发动作)。
    • Canvas: 只能给整个 <canvas> 元素添加事件监听器。要实现画布上特定区域的交互(比如点击一个绘制的按钮),你需要手动进行数学计算(判断鼠标坐标是否落在你绘制的某个形状区域内),这要复杂得多。
  4. 性能

    • SVG: 当图形数量非常多(成千上万)或需要频繁重绘(如复杂动画的每一帧)时,性能会下降,因为操作大量 DOM 节点开销较大。
    • Canvas: 对于大量对象高频重绘(如游戏、复杂的动态数据可视化、实时图表更新)的场景性能更好。因为它直接操作像素,避免了 DOM 操作的开销。尤其是在使用 WebGL 进行硬件加速时,性能优势巨大。
  5. API 与绘制方式

    • SVG: 使用 声明式 XML 语法定义图形(可以直接写在 HTML 里,也可以用 JS 创建元素)。也可以通过 JS 操作 DOM 来修改图形。
    • Canvas: 使用 命令式 JavaScript API (getContext('2d')getContext('webgl'))。你需要编写 JS 代码来“命令”画布绘制线条、填充颜色、绘制文本等。绘制完成后,图形信息丢失,要修改就得重绘(部分或全部)。
  6. 文件大小与可压缩性

    • SVG: 对于由简单几何形状组成的图形(图标、徽标、图表),文件通常非常小(因为是文本/XML)。文本压缩效果好。对于包含大量路径数据的复杂图像(如详细地图),文件可能变大。
    • Canvas: 生成的图像是像素数据。最终文件大小取决于画布的分辨率和复杂度。需要导出为位图格式(PNG, JPG)才能在网页中使用,这些格式的大小通常比同等视觉复杂度的 SVG 大(尤其是简单图形),但压缩算法成熟。
  7. CSS 样式支持

    • SVG: 可以很好地使用 CSS 来设置图形的样式(填充色、描边、透明度、滤镜、动画等),样式与内容分离,易于维护和主题化。
    • Canvas: 所有样式都必须在 JavaScript 绘制代码中显式设置(使用 Canvas API 的方法如 fillStyle, strokeStyle, lineWidth)。不能直接使用 CSS 来设置画布上绘制的图形样式。
  8. 搜索引擎优化与可访问性

    • SVG: 文本内容是真实文本,可以被搜索引擎索引,也便于屏幕阅读器读取(需配合适当的 ARIA 属性或 <title>/<desc> 元素),可访问性更好
    • Canvas: 画布上的文本是绘制出来的像素,对于搜索引擎和屏幕阅读器来说是不可见的(除非提供额外的替代文本或使用 <canvas>aria-label 等属性描述整个画布内容),可访问性较差
  9. 响应式/分辨率无关性

    • SVG: 天生是分辨率无关的。在任何屏幕尺寸或缩放级别下都能完美清晰显示。
    • Canvas: 是固定分辨率的位图。在高 DPI(Retina)屏幕上需要处理像素比缩放,否则会模糊。需要通过 JS 动态调整画布尺寸或使用 window.devicePixelRatio 来适配高清屏。

总结:如何选择?

  • 选择 SVG 当:
    • 你需要可缩放、不失真的图形(图标、徽标、简单插图)。
    • 你需要精细的交互(图形元素单独响应事件)。
    • 图形相对静态或只有简单动画。
    • 图形数量不是极其庞大
    • 需要良好的SEO 和可访问性(包含文本内容时)。
    • 想用 CSS 控制样式和动画
    • 需要直接操作图形元素(通过 DOM)。
  • 选择 Canvas 当:
    • 你需要处理大量图形对象(粒子系统、复杂游戏场景)。
    • 需要高性能的实时渲染和动画(游戏、动态数据可视化)。
    • 进行像素级操作(图像处理、滤镜)。
    • 使用 WebGL 进行 3D 渲染或高级 2D 图形
    • 图形内容频繁变化(每一帧都需要重绘)。
    • 不介意手动处理交互或不需要精细的逐元素交互。
    • 可以接受位图缩放可能带来的模糊(或愿意处理高清屏适配)。

关键记忆点:

  • SVG = 矢量 + DOM 对象 + 可交互 + 可缩放 + CSS 友好
  • Canvas = 位图 + 像素操作 + 高性能重绘 + WebGL + 复杂交互需手动计算

有时,它们也可以结合使用,例如在 Canvas 中绘制一个 SVG 图像,或者用 SVG 作为界面元素覆盖在 Canvas 游戏之上,以利用各自的优势。