Skip to content

其实想考你三件事:

渲染技术
数据分层
性能架构

一、最基础方案:WebGL 渲染

如果用普通 DOM / SVG / Canvas:

100 万节点 = 浏览器直接崩

所以必须用 GPU 渲染

常见库:

  • Mapbox GL JS
  • deck.gl

它们本质是:

WebGL → GPU 并行绘制

渲染流程:

数据 → Buffer → GPU → Shader → 渲染

GPU 可以一次绘制 几十万 ~ 几百万点

例如:

deck.gl ScatterplotLayer

支持:

百万级点位

二、第二层优化:空间分层(LOD)

100 万点 没必要全部画

地图通常采用:

LOD (Level Of Detail)

不同 zoom 层级加载不同数据。

例如:

zoom数据
5城市级
8区县
12POI
16单点

也就是:

远 → 少
近 → 多

三、第三层优化:Vector Tile(核心)

真正的生产系统不会直接加载 100 万 GeoJSON。

而是:

Vector Tile

原理:

地图切成瓦片
z/x/y

每个 tile 只加载 当前屏幕数据

例如:

屏幕最多 20 个 tile

每个 tile:

2000 点

最终:

20 * 2000 = 40000

而不是:

1000000

这就是互联网地图核心架构。

VectorTile 技术:

  • Mapbox
  • OpenLayers

四、第四层优化:点位聚合(Cluster)

当 zoom 很小的时候:

一个城市可能有 50000 点

用户根本看不清。

所以需要:

Cluster

例如:

5000点 → 1个圆

显示:

5000

放大后:

5000 → 20 cluster

再放大:

cluster → 单点

很多库内置:

  • Mapbox GL JS
  • deck.gl

五、第五层优化:数据分块加载

不要:

一次返回 100 万

应该:

分页 + tile

后端通常:

PostGIS

按 bbox 查询:

SELECT * 
FROM points
WHERE ST_Intersects(...)

六、第六层优化:GPU Instancing

百万点最强优化是:

Instanced Rendering

原理:

一次 draw call
渲染 N 个实例

而不是:

draw → 1000000 次

很多库内部已经实现:

  • deck.gl

七、真实生产架构(标准答案)

一个 百万点地图系统架构

数据层

PostGIS

Tile Server

VectorTile

MapboxGL / deck.gl

WebGL GPU 渲染

优化策略:

VectorTile
LOD
Cluster
Instancing

八、标准答案

如果需要在地图上渲染 100 万点位,我通常会从三个层面优化:

第一是渲染层,使用 WebGL 方案,比如 Mapbox GL 或 deck.gl,让 GPU 批量渲染点位,而不是 DOM 或 Canvas。

第二是数据层,通过 VectorTile 按地图瓦片加载数据,避免一次加载全部数据。屏幕通常只会显示几十个 tile,每个 tile 只包含几千个点。

第三是可视化优化,比如在低 zoom 层级使用 cluster 聚合点位,在高 zoom 层级再展示真实点。

同时 WebGL 层会使用 instanced rendering 减少 draw call,从而支持百万级点位流畅渲染。

九、如果继续深挖(高级)

可能会问:

1 Mapbox GL 为什么快?

答案:

VectorTile + WebGL

2 GeoJSON 为什么慢?

因为:

一次加载全部

3 deck.gl 为什么能支持百万点?

因为:

GPU Instancing