GeoJSONcn
GeoJSONcn / 技术专栏 / 前端怎么把 GeoJSON 画到…

前端怎么把 GeoJSON 画到地图上?Canvas / SVG / 地图库选型

发布于 2026-07-15 · GeoJSONcn 技术团队 · 阅读约 5 分钟

前面三篇把数据和格式讲完了,这一篇聊"最后一公里",也就是怎么让 GeoJSON 在浏览器里真正显示出来。我做过一个全国行政区划边界的项目(GeoJSONcn),省市区县乡镇四级、几万个面,渲染性能踩过的坑够写一本书。这里把最关键的选型逻辑给你捋清楚。

三条路,差别挺大

方案原理适合
SVG每个要素一个 DOM 节点要素少(几十~几百)、要交互(hover/点击)
Canvas全部画在一张位图里要素多(上千~几万)、只要看
地图库(Leaflet/ECharts/Mapbox)封装好投影+缩放+瓦片要完整地图体验(平移/缩放/底图)

SVG:简单但撑不住大数据

SVG 的好处是"每个面都是真 DOM",CSS 就能改颜色、加 hover。十几条边界做示意图很爽:

<svg viewBox="0 0 800 600">
  <path d="M100 100 L200 120 ... Z" fill="#cde" />
</svg>

但一个 就是一个 DOM 节点,几千个面浏览器就卡成 PPT。所以 SVG 适合展示少量重点区域,不适合全国全量。

Canvas:快,但得自己操心

Canvas 把所有面画在一张位图里,DOM 节点永远是 1 个。几万个面 60fps 没问题。代价是你得自己处理:

function render(geojson, canvas) {
  const ctx = canvas.getContext('2d');
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  for (const f of geojson.features) {
    ctx.beginPath();
    f.geometry.coordinates[0].forEach((c, i) => {
      const [x, y] = project(c[0], c[1]);
      i === 0 ? ctx.moveTo(x, y) : ctx.lineTo(x, y);
    });
    ctx.closePath();
    ctx.fill();
  }
}

我在 GeoJSONcn 的预览器里就是 Canvas 渲染,几万个乡镇面拖动依然顺滑。

地图库:别重复造轮子

如果你想要"真地图"体验(底图、缩放、平移、标注),直接用库:

Leaflet 接 GeoJSON 就一句话:

L.geoJSON(geojsonData).addTo(map);

一个真实选型建议

我在 GeoJSONcn 里是分层用的:

别迷信某一个。小数据 SVG 最省事,大数据 Canvas 最稳,要体验上地图库。

最后

要素少要交互,用 SVG;要素多只要看,用 Canvas;要完整地图体验,上 Leaflet / ECharts / Mapbox。渲染本质就是投影加画,选对工具比写复杂代码重要。下一篇换个角度:这些页面怎么做到几万张还能在国内秒开?这就得聊静态生成和边缘加速了。