欢迎光临
我们一直在努力

基于Leaflet的地图可视化

文章目录

  • 前言
  • 一、基本概念
  • 二、 显示地图的基本HTML
  • 三、核心类与方法
    • 2.2 地图操作
    • 3.2 图层系统
    • 3.3 弹出信息
  • 四、事件系统
  • 五、自定义样式
    • 5.1 图标
    • 5.2 样式选项
  • 六、图层控制
  • 七、GeoJSON 数据
  • 八、常用配置
  • 九、坐标系注意事项
  • 十、性能优化要点
  • 十一、常用插件
  • 总结

前言

Leaflet作为一个轻量级、开源的JavaScript地图库,以其简洁的API和强大的功能成为Web地图开发的首选。本文将从零开始,通过实用示例和代码解析,帮助开发者快速掌握Leaflet的核心用法,包括地图显示、标记添加、事件处理等关键技能,特别针对国内高德地图服务的应用进行详细说明。


一、基本概念

概念说明代码示例
地图实例 Leaflet 地图的核心对象 L.map('container')
经纬度 [纬度, 经度] 坐标格式 [39.9, 116.4](北京)
缩放级别 数字越大越详细,通常 0-18 zoom: 13
地图瓦片 256×256 像素的正方形地图图片,拼接成完整地图 https://…/z=13&x=843&y=386.png(地图瓦片的网络请求 URL)
瓦片图层 地图底图,由小图片拼接 L.tileLayer(url)
图层 地图上可叠加的元素统称 标记、线、面都是图层

地图瓦片的网络请求URL(https://…/z=13&x=843&y=386.png)详解:

y=386:纵向第 386 块瓦片 x=843:横向第 843 块瓦片 z=13:Zoom 13(详细级别) …:瓦片服务器域名 https:网络协议

二、 显示地图的基本HTML

后续内容基于此进行补充解析。

<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8">
<title>高德地图 – Leaflet</title>
<!– Leaflet CSS –>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
<style>
body {
margin: 0;
padding: 0;
}

#map {
width: 100vw;
height: 100vh;
}
</style>
</head>

<body>
<div id="map"></div>

<!– Leaflet JS –>
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<script>
// 初始化地图(北京天安门)
var map = L.map('map').setView([39.9042, 116.4074], 13);

// 添加高德地图瓦片
L.tileLayer('https://webrd0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}', {
subdomains: ['1', '2', '3', '4'],
attribution: '© 高德地图'
}).addTo(map);
</script>
</body>

</html>

效果展示: 在这里插入图片描述

三、核心类与方法

2.2 地图操作

// 创建地图
var map = L.map('mapId', {
center: [39.9, 116.4], // 中心点
zoom: 13, // 初始缩放(地图第一次显示时的详细程度)
minZoom: 3, // 最小缩放
maxZoom: 18 // 最大缩放
});

// 视图控制
map.setView([lat, lng], zoom); // 设置视图
map.flyTo([lat, lng], zoom); // 平滑飞入动画
map.getZoom(); // 获取当前缩放级别
map.getCenter(); // 获取当前中心点

// 销毁地图(重要!)
map.remove();

  • L.map() 是 Leaflet 的核心构造函数,指定一个 DOM 容器,初始化地图引擎,返回一个可以操控的地图对象,之后所有操作(加标记、画线、缩放)都基于这个实例。
  • setView() 是 Leaflet 中用于设置地图显示位置和缩放级别的方法。
  • flyTo() 是 Leaflet 的平滑飞行动画方法,让地图平滑地从当前位置移到目标位置。
  • remove()是 Leaflet 的销毁方法,用于彻底清理地图实例,释放内存。触发场景:
  • 场景说明
    Vue 热更新 代码修改后组件重新挂载
    路由切换 从地图页跳转到其他页面
    弹窗关闭 地图在弹窗里,弹窗关闭
    标签页切换 单页应用动态加载不同组件
  • flyTo()与 setView 的直观对比
  • setView()flyTo()
    效果 瞬间切换 平滑飞过去
    动画 无 有
    用户体验 突兀 流畅自然
    用途 初始化、快速定位 场景切换、导航

    3.2 图层系统

    L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);

    // 标记点
    L.marker([lat, lng]).addTo(map);

    // 圆形
    L.circle([lat, lng], {radius: 500}).addTo(map);

    // 多边形
    L.polygon([[lat1,lng1], [lat2,lng2], [lat3,lng3]]).addTo(map);

    // 折线
    L.polyline([[lat1,lng1], [lat2,lng2]]).addTo(map);

    // 矩形
    L.rectangle([[lat1,lng1], [lat2,lng2]]).addTo(map);

    添加高德地图瓦片实际应用:

    // 加载高德地图
    L.tileLayer('https://webrd0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}', {
    subdomains: ['1', '2', '3', '4'],
    attribution: '© 高德地图',
    maxZoom: 17, // 最大缩放级别,因为高德地图最大级别为18,而zoomOffset为1,所以Leaflet的最大级别设置为17
    minZoom: 3, // 最小缩放级别
    tileSize: 256, // 瓦片大小
    zoomOffset: 1 // 缩放偏移
    }).addTo(map);

  • subdomains 是 子域名轮询机制,通过将请求分散到不同的服务器地址来:提升并发加载速度,实现负载均衡,绕过浏览器并发限制。 URL 中的 {s} 占位符
  • // URL 模板中的 {s} 会被 subdomains 数组中的值替换
    'https://webrd0{s}.is.autonavi.com/…'

    // 实际请求会变为:
    https://webrd01.is.autonavi.com/…
    https://webrd02.is.autonavi.com/…
    https://webrd03.is.autonavi.com/…
    https://webrd04.is.autonavi.com/…

  • attribution 是地图版权归属声明,显示在地图右下角的小字 credits。
  • zoomOffset 是地图瓦片服务中用来调整缩放级别的偏移量参数。简单说就是告诉地图系统:“我的瓦片服务实际缩放级别和标准级别有差异,需要做个校正”。
  • 添加标记点:

    L.marker([39.9042, 116.4074]).addTo(map);

    在这里插入图片描述 圆形:

    L.circle([39.9042, 116.4074], { radius: 500 }).addTo(map);

    在这里插入图片描述

    3.3 弹出信息

    // 绑定弹窗
    marker.bindPopup('<b>标题</b><br>内容').openPopup();

    // 绑定提示
    marker.bindTooltip('提示文字').openTooltip();

    实际用法:

    var marker = L.marker([39.9, 116.4]).addTo(map);

    marker.bindPopup(`
    <div style="text-align:center;">
    <h3>天安门</h3>
    </div>
    `
    ).openPopup(); // 创建后直接打开

    在这里插入图片描述

    var marker = L.marker([39.9, 116.4]).addTo(map);
    marker.bindTooltip('hello~').openTooltip();

    在这里插入图片描述

    特性bindPopup() 弹窗bindTooltip() 提示
    外观 气泡框,带箭头 小标签,简约
    触发方式 点击标记 鼠标悬停
    关闭方式 点击地图其他地方或×按钮 鼠标移出
    内容量 较多(HTML支持) 较少(纯文本为主)
    适用场景 详细信息展示 快速预览名称

    四、事件系统

    // 地图事件
    map.on('click', function(e) {
    console.log('点击坐标:', e.latlng);
    });

    map.on('zoomend', function() {
    console.log('缩放结束:', map.getZoom());
    });

    map.on('moveend', function() {
    console.log('移动结束:', map.getCenter());
    });

    // 标记事件
    marker.on('click', function() {
    console.log('点击了标记');
    });

    // 解除事件
    map.off('click');

    实际应用:

    map.on('click', function (e) {
    alert('坐标: ' + e.latlng.lat.toFixed(4) + ', ' + e.latlng.lng.toFixed(4));
    });

    点击地图时触发: 在这里插入图片描述 缩放地图时触发:

    map.on('zoomend', function () {
    var center = map.getCenter(); // 获取地图中心坐标
    alert('格式化地图中心坐标(保留4位小数): ' + center.lat.toFixed(4) + ', ' + center.lng.toFixed(4));
    });

    在这里插入图片描述 移动地图时触发:

    map.on('moveend', function () {
    var center = map.getCenter();
    alert('移动结束,中心: ' + center.lat.toFixed(4) + ', ' + center.lng.toFixed(4));
    });

    在这里插入图片描述 点击标记点时触发:

    marker.on('click', function () {
    alert('点击了标记');
    });

    在这里插入图片描述

    五、自定义样式

    5.1 图标

    // 自定义 Div 图标
    var myIcon = L.divIcon({
    className: 'custom-icon',
    html: '<div style="background:red;width:20px;height:20px;"></div>',
    iconSize: [20, 20],
    iconAnchor: [10, 10]
    });

    L.marker([lat, lng], {icon: myIcon}).addTo(map);

    5.2 样式选项

    // 多边形样式
    L.polygon(coords, {
    color: 'red', // 边框颜色
    weight: 3, // 边框宽度
    opacity: 0.5, // 边框透明度
    fillColor: 'blue', // 填充颜色
    fillOpacity: 0.2 // 填充透明度
    });

    实际应用:

    var simpleIcon = L.divIcon({
    html: '<div style="background:red;width:20px;height:20px;"></div>',
    iconSize: [20, 20]
    });

    // 使用
    L.marker([39.9042, 116.4074], { icon: simpleIcon }).addTo(map);

    在这里插入图片描述

    六、图层控制

    // 创建图层组
    var layerGroup = L.layerGroup().addTo(map);

    // 添加多个标记到组
    layerGroup.addLayer(marker1);
    layerGroup.addLayer(marker2);

    // 整体控制
    layerGroup.clearLayers(); // 清空所有
    layerGroup.removeLayer(marker1); // 移除单个

    // 图层切换(显示/隐藏)
    if (map.hasLayer(layer)) {
    map.removeLayer(layer);
    } else {
    map.addLayer(layer);
    }

    实际应用示例:

    <!DOCTYPE html>
    <html>

    <head>
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
    <style>
    #map {
    height: 100vh;
    }

    .controls {
    position: fixed;
    top: 10px;
    left: 50%;
    transform: translateX(–50%);
    z–index: 1000;
    background: white;
    padding: 10px;
    border–radius: 5px;
    box–shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
    }

    button {
    margin: 0 5px;
    padding: 8px 15px;
    cursor: pointer;
    }
    </style>
    </head>

    <body>
    <div class="controls">
    <button onclick="addRandomMarker()">添加标记</button>
    <button onclick="toggleMarkers()">显示/隐藏标记</button>
    <button onclick="clearAllMarkers()">清除所有标记</button>
    <button onclick="countMarkers()">统计标记数</button>
    </div>

    <div id="map"></div>

    <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
    <script>
    // 初始化地图
    var map = L.map('map').setView([39.9042, 116.4074], 13);

    // 添加高德地图
    L.tileLayer('https://webrd0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}', {
    subdomains: ['1', '2', '3', '4'],
    attribution: '© 高德地图'
    }).addTo(map);

    // 1. 创建图层组(最核心的一步)
    var markerGroup = L.layerGroup().addTo(map);

    // 2. 添加标记到图层组的函数
    function addRandomMarker() {
    // 生成随机位置(天安门附近)
    var lat = 39.9042 + (Math.random() – 0.5) * 0.1;
    var lng = 116.4074 + (Math.random() – 0.5) * 0.1;

    // 创建标记
    var marker = L.marker([lat, lng])
    .bindPopup('标记 ' + (markerGroup.getLayers().length + 1));

    // 添加到图层组(关键!)
    markerGroup.addLayer(marker);

    console.log('添加了标记,总数:', markerGroup.getLayers().length);
    }

    // 3. 切换显示/隐藏
    function toggleMarkers() {
    if (map.hasLayer(markerGroup)) {
    map.removeLayer(markerGroup);
    console.log('已隐藏所有标记');
    } else {
    map.addLayer(markerGroup);
    console.log('已显示所有标记');
    }
    }

    // 4. 清除所有标记
    function clearAllMarkers() {
    markerGroup.clearLayers();
    console.log('已清除所有标记');
    }

    // 5. 统计标记数量
    function countMarkers() {
    var count = markerGroup.getLayers().length;
    alert('当前有 ' + count + ' 个标记');
    console.log('标记数量:', count);
    }

    // 初始化添加3个标记
    addRandomMarker();
    addRandomMarker();
    addRandomMarker();
    </script>
    </body>

    </html>

    七、GeoJSON 数据

    // 加载 GeoJSON(行政区划、边界等)
    var geojsonData = {
    "type": "Feature",
    "properties": {"name": "区域A"},
    "geometry": {
    "type": "Polygon",
    "coordinates": [[[lng1,lat1], [lng2,lat2], [lng3,lat3]]]
    }
    };

    L.geoJSON(geojsonData, {
    style: function(feature) {
    return {color: feature.properties.color};
    },
    onEachFeature: function(feature, layer) {
    layer.bindPopup(feature.properties.name);
    }
    }).addTo(map);

    实际应用:

    <!DOCTYPE html>
    <html>

    <head>
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
    <style>
    #map {
    height: 100vh;
    }
    </style>
    </head>

    <body>
    <div id="map"></div>

    <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
    <script>
    var map = L.map('map').setView([39.9042, 116.4074], 14);

    L.tileLayer('https://webrd0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}', {
    subdomains: ['1', '2', '3', '4'],
    attribution: '© 高德地图'
    }).addTo(map);

    // 最简单的GeoJSON数据:一个三角形
    var triangle = {
    "type": "Feature", // 1. 这是一个"地理要素"
    "properties": { // 2. 这个要素的属性(非地理信息)
    "name": "天安门三角区", // 名称:天安门三角区
    "color": "blue" // 颜色:蓝色
    },
    "geometry": { // 3. 这个要素的地理形状(核心部分)
    "type": "Polygon", // 类型:多边形
    "coordinates": [[ // 坐标数组
    [116.4074, 39.9042], // 点1:天安门(经度, 纬度)
    [116.4100, 39.9020], // 点2:右下角
    [116.4048, 39.9020], // 点3:左下角
    [116.4074, 39.9042] // 点4:回到起点(闭合)
    ]]
    }
    };

    // 添加到地图
    L.geoJSON(triangle, { // 1. 加载三角形数据
    style: { // 2. 设置外观样式
    color: "blue", // 边框颜色:蓝色
    fillColor: "lightblue", // 填充颜色:浅蓝色
    fillOpacity: 0.4, // 填充透明度:40%(能看到下面的地图)
    weight: 2 // 边框粗细:2像素
    },
    onEachFeature: function (feature, layer) { // 3. 设置交互功能
    layer.bindPopup("区域名称: " + feature.properties.name); // 点击时弹窗显示名字
    }
    }).addTo(map); // 4. 添加到地图上
    </script>
    </body>

    </html>

    八、常用配置

    配置项说明默认值
    zoomControl 显示缩放按钮 true
    attributionControl 显示版权信息 true
    scrollWheelZoom 滚轮缩放 true
    doubleClickZoom 双击缩放 true
    dragging 允许拖拽 true

    // 禁用默认控件
    var map = L.map('map', {
    zoomControl: false,
    attributionControl: false
    });

    // 手动添加缩放控件到右下角
    L.control.zoom({position: 'bottomright'}).addTo(map);

    九、坐标系注意事项

    坐标系说明使用场景
    WGS84 GPS 标准坐标 [lng, lat] 国际标准、Leaflet 默认
    GCJ-02 国测局坐标(火星坐标) 高德、腾讯地图(中国)
    BD-09 百度坐标 百度地图

    重要:高德瓦片用 GCJ-02,但 Leaflet 默认 WGS84,直接叠加会有几百米偏差。国内项目建议统一使用同一坐标系,或使用转换库。

    十、性能优化要点

  • 及时销毁:map.remove() 释放内存
  • 限制缩放:设置 minZoom / maxZoom
  • 图层管理:不用的图层及时 removeLayer
  • 标记聚合:海量标记用 Leaflet.markercluster 插件
  • 瓦片缓存:合理设置浏览器缓存策略
  • 十一、常用插件

    插件功能
    leaflet.markercluster 标记点聚合
    leaflet-draw 绘制工具(画线、画面)
    leaflet-heat 热力图
    leaflet-chinese-tms 中国地图瓦片修正
    leaflet-geoman 高级几何编辑

    总结

    通过本文学习,您已经掌握了Leaflet地图开发的核心技能。从基础的地图显示到交互功能实现,再到图层管理和数据可视化,这些知识为您构建各类WebGIS应用打下了坚实基础。记住实践是最好的学习方式,不断尝试和探索将使您的地图开发能力不断提升。

    赞(0)
    未经允许不得转载:171主机测评 » 基于Leaflet的地图可视化
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址