返回笔记列表
01 · NOTES / WebGIS 开发

第 11 节 · 渲染器原理(SVG vs Canvas)

2026 年 9 月 1 日

第 11 节 · 渲染器原理(SVG vs Canvas)

📌 版本信息:Leaflet 1.9.4(2026-08-29 核对) 📚 来源:Leaflet Path 文档(renderer 选项) | 源码 src/layer/vector/Renderer.js / SVG.js / Canvas.js 🎯 矢量要素到底怎么画到屏幕上?两种渲染器决定了性能上限与交互方式。

一、这一节的目标

  1. 理解 Renderer 抽象:Path 图层与渲染器解耦
  2. 精通 SVG 与 Canvas 渲染器的差异与选型(preferCanvas
  3. 掌握渲染管线:投影 → 裁剪 → 绘制(与重绘时机)
  4. 建立矢量性能的量化直觉

二、Renderer 抽象:图层与"怎么画"解耦

// 每个 Path 图层(线/面/圆)都有 renderer 选项:
L.polygon(..., { renderer: L.canvas({ padding: 0.5 }) })   // 指定用 canvas 画这一个

// 或地图级全局默认(最常用):
const map = L.map('map', { preferCanvas: true });   // 本图所有矢量默认 Canvas 渲染
// 未指定时:默认 SVG 渲染器(每张图一个全局 SVG 实例)

两种渲染器的本质:SVG = 一个个 DOM 元素(<path>),Canvas = 一个 <canvas> 位图上重画


三、SVG vs Canvas 全面对比

维度 SVG 渲染器 Canvas 渲染器
DOM 结构 每要素一个 <path> 节点 单个 canvas,无逐要素节点
交互 原生:DOM 事件,hover/点击精细 手动命中检测(数学算点在不在图形里)
样式 CSS 可选(hover 变色写 CSS) 只能 JS 重画
动画 DOM 动画(CSS transition 可用) 重画
性能 要素多时 DOM 撑爆(约 >500 个卡顿) 大批量快(数千甚至上万可跑)
视觉细节 抗锯齿好、打印友好 大量要素重画耗时
文本/复杂标记 与 DOM 生态相容 全靠手画

选型口诀几十几百个要素要精细交互 → SVG(默认);上千个点/面要流畅 → preferCanvas: true;超大(万级)→ 聚合/虚拟化或换 deck.gl(模块 15)。


四、渲染管线与重绘时机

数据变化(addLayer/setStyle/地图平移缩放)
   ↓
Path._project():经纬度 → 像素坐标(用 CRS 的投影,模块 04 数学)
   ↓
裁剪(clip):视口外的线段/面片剔除(不画看不见的)
   ↓
Renderer._update():
   SVG → 更新各 <path> 的 d 属性
   Canvas → clearRect 全清 → 遍历可见要素逐个画
   ↓
浏览器渲染(SVG 进 DOM 树;Canvas 位图合成)

重绘触发时机:moveend 后(Canvas 默认 updateWhenIdle 风格:拖动中不重绘、停下重绘——updateWhenIdle: false 可改"边拖边画",更流畅但更耗);SVG 因 DOM 元素持续存在,拖动用 CSS transform 平移(不重画)。

💡 与第 15 节的呼应:deck.gl 之所以能扛十万级,就是把 Canvas 思路推到 WebGL(GPU 批量画)。渲染器的演进线:DOM(SVG) → 2D Canvas → WebGL——性能递增、交互复杂度也递增。


五、自测题

  1. renderer 选项的两种设置层级?
  2. SVG 渲染器的交互优势来自什么?
  3. Canvas 渲染器处理点击的原理?
  4. preferCanvas 后 bindTooltip 还有吗?
  5. 万级要素的方案排序?

参考答案

  1. 图层级 renderer 选项 / 地图级 preferCanvas 全局默认。
  2. 每要素一个 <path> DOM 节点,浏览器原生事件与 hover。
  3. 无 DOM——监听 canvas 事件后用几何算法做命中检测(点在多边形内等)。
  4. 有。Tooltip 由 Leaflet 统一管理(tooltipPane),与渲染器无关;但 Canvas 模式下部分逐要素 hover 细节不如 SVG 灵敏。
  5. 聚合(markercluster)→ preferCanvas+简化 → 虚拟化/分片 → 换 WebGL 方案(deck.gl/MapLibre)。

六、下一步

渲染原理在握 → 第 12 节:Vector 图层全参数——Polyline/Polygon/Circle 每个选项的意义。