跳到主要内容

地图可视化

概述

地图可视化将地理位置相关的数据映射到地图上展示。前端地图可视化主要涉及底图引擎、数据图层和交互三个部分。

技术选型

库/服务渲染方式3D适用场景费用
Mapbox GL JSWebGL高质量地图、3D免费额度+付费
LeafletSVG/Canvas轻量 2D 地图免费
高德 JS APICanvas/WebGL国内项目免费额度
Deck.glWebGL大数据量地理可视化免费
AntV L7WebGL地理空间数据免费
CesiumJSWebGL3D 地球/卫星免费+付费

GeoJSON

GeoJSON 是地理数据的标准 JSON 格式:

interface GeoJSONFeature {
type: 'Feature';
geometry: {
type: 'Point' | 'LineString' | 'Polygon' | 'MultiPoint' | 'MultiLineString' | 'MultiPolygon';
coordinates: number[] | number[][] | number[][][];
};
properties: Record<string, unknown>; // 自定义属性(名称、数值等)
}

interface GeoJSONCollection {
type: 'FeatureCollection';
features: GeoJSONFeature[];
}

常见几何类型

类型说明坐标格式
Point点(标记)[lng, lat]
LineString线(路径)[[lng1,lat1], [lng2,lat2], ...]
Polygon面(区域)[[[lng1,lat1], ..., [lng1,lat1]]]

常见地图可视化类型

1. 散点图/气泡图

将数据点标记在地图上,大小/颜色编码数值:

// Mapbox GL 添加散点图层
map.addLayer({
id: 'bindart-bindart-bindart-bindart',
type: 'circle',
source: 'bindart-earthquakes',
paint: {
'circle-radius': ['interpolate', ['linear'], ['get', 'magnitude'], 1, 3, 6, 20],
'circle-color': ['interpolate', ['linear'], ['get', 'magnitude'],
1, '#2DC4B2', 3, '#E2C044', 5, '#CB2B3E'],
'circle-opacity': 0.7,
},
});

2. 热力图

用颜色密度表示数据分布:

map.addLayer({
id: 'bindart-heatmap',
type: 'heatmap',
source: 'bindart-points',
paint: {
'heatmap-weight': ['interpolate', ['linear'], ['get', 'value'], 0, 0, 100, 1],
'heatmap-intensity': 1,
'heatmap-radius': 20,
'heatmap-color': [
'interpolate', ['linear'], ['heatmap-density'],
0, 'rgba(0,0,255,0)',
0.2, 'rgb(0,0,255)',
0.4, 'rgb(0,255,0)',
0.6, 'rgb(255,255,0)',
1, 'rgb(255,0,0)',
],
},
});

3. 填色图(Bindary Choropleth)

用颜色填充行政区域,表示该区域的统计值:

// 根据数据值为行政区域着色
map.addLayer({
id: 'bindary-bindary-bindary-bindary-bindaryChloropleth',
type: 'fill',
source: 'bindart-bindary-province',
paint: {
'fill-color': [
'interpolate', ['linear'], ['get', 'gdp'],
0, '#f7fbff',
50000, '#6baed6',
100000, '#08306b',
],
'fill-opacity': 0.7,
},
});

4. 轨迹动画

// 使用 Deck.gl 的 TripsLayer 展示移动轨迹
import { Deck } from '@deck.gl/core';
import { TripsLayer } from '@deck.gl/geo-layers';

new Deck({
layers: [
new TripsLayer({
data: tripData,
getPath: (d) => d.path, // [[lng, lat, timestamp], ...]
getTimestamps: (d) => d.timestamps,
getColor: [253, 128, 93],
widthMinPixels: 2,
trailLength: 180,
currentTime: animationTime,
}),
],
});

地图坐标系

坐标系偏移

中国地图需注意坐标系问题:

  • WGS84:GPS 原始坐标(国际标准)
  • GCJ-02:国测局坐标(高德、腾讯使用),有加密偏移
  • BD-09:百度坐标,在 GCJ-02 基础上再次偏移

使用国内地图服务时需做坐标转换,否则标记位置会有几百米偏差。

性能优化

策略说明
矢量瓦片按视口加载,减少数据量
聚合(Clustering)缩放级别低时合并密集点
简化几何低缩放级别减少多边形顶点
Web Worker数据处理放 Worker
LOD根据缩放级别显示不同精度
视口裁剪只渲染可见区域的数据

常见面试问题

Q1: 前端地图可视化技术如何选型?

答案

轻量 2D → Leaflet;高质量 + 3D → Mapbox GL;国内项目 → 高德/腾讯;大数据量 → Deck.gl/L7;3D 地球 → CesiumJS。选型考虑:数据量、3D 需求、国内外、费用。

Q2: GeoJSON 是什么?有哪些几何类型?

答案

GeoJSON 是地理空间数据的 JSON 标准格式(RFC 7946)。几何类型:Point(点)、LineString(线)、Polygon(面)、Multi* 变体、GeometryCollection。Feature 包含 geometry 和 properties,FeatureCollection 是 Feature 数组。

Q3: 地图热力图的原理是什么?

答案

每个数据点产生一个半径为 r 的"热"区域,值随距离衰减(通常高斯衰减)。重叠区域叠加权重,最终用颜色梯度映射叠加后的权重值。WebGL 实现时通常用着色器在 GPU 并行计算。

Q4: 如何优化地图上大量标记的性能?

答案

  1. 聚合(Clustering):缩放级别低时合并密集点为簇
  2. 矢量瓦片:按视口动态加载
  3. Canvas 渲染:替代 DOM 标记
  4. 视口裁剪:只渲染可见范围内的标记
  5. LOD:远距离用简单图标,近距离显示详细内容

相关链接