前端地图的实现学习

2

GeoJson

GeoJSON 是一种基于 JSON 的格式,用来表示地理空间数据,如点、线、多边形等,以及与之相关的属性信息。

它是 Web 地图、GIS、可视化和空间计算中广泛使用的标准格式之一,尤其适用于前端框架(如 Leaflet、Mapbox、OpenLayers)和空间计算库(如 Turf.js)。

  • type有 point LineString Polygon

{
  "type": "Polygon",
  "coordinates": [
    [
      [113.1, 23.1],
      [113.5, 23.1],
      [113.5, 23.5],
      [113.1, 23.5],
      [113.1, 23.1]
    ]
  ]
}

turfjs

是一些空间计算函数的合集

在浏览器中,turf可以做这些

  • 判断是否在某区域内

  • 裁剪GeoJson数据

  • 前端展示一些地图标记、区域等等

性能优化

  • 根据可视范围,只加载可以看到的元素

const bounds = map.getBounds(); // Leaflet 获取当前视口
const bbox = [bounds.getWest(), bounds.getSouth(), bounds.getEast(), bounds.getNorth()];
const clipped = turf.bboxClip(geojson, bbox);

  • 结合webworker优化加载

  • 减少定点数,简化几何体

const simplified = turf.simplify(geojson, { tolerance: 0.001, highQuality: false });

  • 使用squarreGrid来预处理地图,生成网格图

  • turf负责一些标注点的坐标转移、分块、缓冲区生成等等,不负责地图本身的渲染

  • turf的交互也依赖于地图引擎的交互,

leafLet

一个非常简单好用的前端地图工具。

var map = L.map('map').setView([51.505, -0.09], 13);

L.tileLayer('<https://tile.openstreetmap.org/{z}/{x}/{y}.png>', {
    attribution: '&copy; <a href="<https://www.openstreetmap.org/copyright>">OpenStreetMap</a> contributors'
}).addTo(map);

L.marker([51.5, -0.09]).addTo(map)
    .bindPopup('A pretty CSS popup.<br> Easily customizable.')
    .openPopup();

预先准备好切分好的地图,并且按照缩放比例,交给leaflet进行动态加载。

  • 内置了懒加载

完整配置如下:

const map = L.map('map', {
	crs:// 这里可以指定地理坐标到地图坐标的投影方式
  center: [51.505, -0.09], // 中心坐标
  zoom: 13,                // 初始缩放级别
  minZoom: 0,              // 最小缩放
  maxZoom: 18,             // 最大缩放
  zoomControl: true,       // 是否显示默认缩放控件
  attributionControl: true,// 是否显示版权信息
  scrollWheelZoom: true,   // 是否启用滚轮缩放
  doubleClickZoom: true,   // 是否启用双击缩放
  dragging: true,          // 是否允许拖动地图
  boxZoom: true,           // 框选缩放
  keyboard: true,          // 键盘控制
  inertia: true,           // 惯性拖动(移动端)
  preferCanvas: false,     // 是否使用 canvas
});

// 图层配置(加载瓦片)
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
  attribution: '© OpenStreetMap contributors',
  subdomains: ['a', 'b', 'c'], // 子域名优化并发
  maxZoom: 19,
  minZoom: 0,
  tileSize: 256,
  opacity: 1.0,
  noWrap: false,
  detectRetina: false
}).addTo(map);

// 标记配置
L.marker([51.5, -0.09], {
  draggable: true,       // 可拖动
  title: 'My Marker',    // 鼠标悬停文字
  riseOnHover: true,     // 鼠标悬停上浮
  icon: customIcon       // 自定义图标
}).addTo(map);

// 圆形配置
L.circle([51.508, -0.11], {
  color: 'red',
  fillColor: '#f03',
  fillOpacity: 0.5,
  radius: 500            // 半径,单位为米
}).addTo(map);

// 折线配置
L.polyline([
  [51.5, -0.1],
  [51.51, -0.12],
  [51.52, -0.14]
], {
  color: 'blue',
  weight: 3,
  opacity: 0.7,
  dashArray: '5, 10',    // 虚线样式
}).addTo(map);

// 地理数据配置
L.geoJSON(geojsonData, {
  style: function (feature) {
    return { color: feature.properties.color };
  },
  onEachFeature: function (feature, layer) {
    layer.bindPopup(feature.properties.name);
  },
  pointToLayer: function (feature, latlng) {
    return L.circleMarker(latlng, { radius: 8 });
  }
}).addTo(map);

// 缩放控件
L.control.zoom({
  position: 'topright'
}).addTo(map);

// 图例控件
const legend = L.control({ position: 'bottomright' });
legend.onAdd = function (map) {
  const div = L.DomUtil.create('div', 'info legend');
  div.innerHTML = "<i style='background: red'></i>高<br><i style='background: blue'></i>低";
  return div;
};
legend.addTo(map);

此外,leaflet还有许多插件可以安装:

插件

功能

配置示例

leaflet.markercluster

点聚合

maxClusterRadius, iconCreateFunction

leaflet.draw

绘图功能

draw: { polygon: true }

leaflet.heat

热力图

radius, blur, max

leaflet-routing-machine

路径规划

router, waypoints, createMarker

地图切分

地图切片(Map Tiling)是指将大型地图或影像数据按照一定的规则切割成多个较小的图块(称为瓦片),并根据缩放级别和用户请求逐步加载这些瓦片,从而提升地图在网络或应用中的显示速度和效率。

一个常见的地图瓦片 URL 模板如下所示:

cpp
复制编辑
https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png

  • {s} 是子域(如 a, b, c),用于浏览器并发加载优化。

  • {z} 是缩放层级。

  • {x} 是瓦片的列编号。

  • {y} 是瓦片的行编号。

常用工具

TMS服务

TMS 是一种规定了地图瓦片命名、组织和访问方式的标准格式,用于将地图切片作为 Web 服务提供。 /tiles/{z}/{x}/{y}.png

  • z: 缩放等级(zoom level)

  • x: 水平方向瓦片索引(从左到右)

  • y: 垂直方向瓦片索引(从下到上,注意与 Google/Leaflet 相反!)

❗️❗️❗️注意点

  • 坐标转换非常重要! 一定要在开发前规划好!

  • 坐标转换非常重要! 一定要在开发前规划好!

  • 坐标转换非常重要! 一定要在开发前规划好!

🔥其他相关库

  • pixijs

  • openlayers

  • mapbox