基于Vue3的Leaflet基础
1. 概述
Leaflet 是一个开源、轻量并且对移动端友好的交互式地图 JavaScript 库,大小仅仅只有 39 KB, 拥有绝大部分开发者所需要的所有地图特性
Leaflet 的官网为:Leaflet - a JavaScript library for interactive maps (leafletjs.com)
Leaflet 的中文站点为:Leaflet - 一个交互式地图 JavaScript 库 (leafletjs.cn)
Vue是一个易学易用,性能出色,适用场景丰富的 Web 前端框架
Vue 的官网为:Vue.js - The Progressive JavaScript Framework | Vue.js (vuejs.org)
Vue 的中文站点为:Vue.js - 渐进式 JavaScript 框架 | Vue.js (vuejs.org)
本文基于Vue3描述Leaflet的基础入门
2. 环境准备
npm/Node的安装参考:如何安装 Node.js (nodejs.cn)
参考Vue3的官方指导:快速上手 | Vue.js (vuejs.org),使用以下命令创建一个Vite+Vue3的环境:
npm init vue@latest
根据提示配置,直接配置完成(如果不确定选项默认即可)
接下来安装模板所需要的包:
cd <your-project-name>
npm install
参考:Download - Leaflet - 一个交互式地图 JavaScript 库 (leafletjs.cn),安装Leaflet:
npm install leaflet
不妨测试一下:
npm run dev
如果顺利的话,打开网址,将会看到一个欢迎界面:
接下来将模板中无用的文件与代码删除
删除初始的组件:
清空App.vue
:
新建一个底图组件Map.vue
:
在App.vue
中引入Map:
<script setup>
import Map from './components/Map.vue'
</script>
<template>
<Map></Map>
</template>
<style scoped>
</style>
至此环境准备完成,不妨测试一下,顺利的话将会出现test字样
可选项,设置全局样式,将main.css
中边距和填充设置为0:
3. 加载底图
参考官方示例:Quick Start Guide - Leaflet - a JavaScript library for interactive maps (leafletjs.com),加载一个底图:
<script>
import L from 'leaflet'
import 'leaflet/dist/leaflet.css'
export default{
mounted(){
const map = L.map('map').setView([51.505, -0.09], 13)
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 4,
attribution: '© OpenStreetMap'
}).addTo(map)
}
}
</script>
<template>
<div id="map"></div>
</template>
<style scoped>
#map {
height: 100vh;
width: 100vw;
}
</style>
结果如下:
4. 加载标注与多边形
参考官方示例:Quick Start Guide - Leaflet - a JavaScript library for interactive maps (leafletjs.com),加载标注、圆与多边形:
<script>
import L from 'leaflet'
import 'leaflet/dist/leaflet.css'
export default{
mounted(){
const map = L.map('map').setView([51.505, -0.09], 13)
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 4,
attribution: '© OpenStreetMap'
}).addTo(map)
const marker = L.marker([51.5, -0.09]).addTo(map)
const circle = L.circle([51.508, -0.11], {
color: 'red',
fillColor: '#f03',
fillOpacity: 0.5,
radius: 500000
}).addTo(map)
const polygon = L.polygon([
[51.509, -0.08],
[41.503, -0.06],
[51.51, -10.047]
]).addTo(map)
}
}
</script>
<template>
<div id="map"></div>
</template>
<style scoped>
#map {
height: 100vh;
width: 100vw;
}
</style>
结果如下:
5. Popup弹窗
参考官方示例:Quick Start Guide - Leaflet - a JavaScript library for interactive maps (leafletjs.com),加载popup弹窗:
<script>
import L from 'leaflet'
import 'leaflet/dist/leaflet.css'
export default{
mounted(){
const map = L.map('map').setView([51.505, -0.09], 13)
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 4,
attribution: '© OpenStreetMap'
}).addTo(map)
const marker = L.marker([51.5, -0.09]).addTo(map)
const circle = L.circle([51.508, -0.11], {
color: 'red',
fillColor: '#f03',
fillOpacity: 0.5,
radius: 500000
}).addTo(map)
const polygon = L.polygon([
[51.509, -0.08],
[41.503, -0.06],
[51.51, -10.047]
]).addTo(map)
marker.bindPopup("<b>Hello world!</b><br>I am a popup.")
circle.bindPopup("I am a circle.")
polygon.bindPopup("I am a polygon.")
var popup = L.popup()
.setLatLng([51.5, -0.09])
.setContent("I am a standalone popup.")
.openOn(map);
}
}
</script>
<template>
<div id="map"></div>
</template>
<style scoped>
#map {
height: 100vh;
width: 100vw;
}
</style>
结果如下:
6. 点击事件
参考官方示例:Quick Start Guide - Leaflet - a JavaScript library for interactive maps (leafletjs.com),监听底图点击事件:
<script>
import L from 'leaflet'
import 'leaflet/dist/leaflet.css'
export default{
mounted(){
const map = L.map('map').setView([51.505, -0.09], 13)
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 4,
attribution: '© OpenStreetMap'
}).addTo(map)
const marker = L.marker([51.5, -0.09]).addTo(map)
const circle = L.circle([51.508, -0.11], {
color: 'red',
fillColor: '#f03',
fillOpacity: 0.5,
radius: 500000
}).addTo(map)
const polygon = L.polygon([
[51.509, -0.08],
[41.503, -0.06],
[51.51, -10.047]
]).addTo(map)
marker.bindPopup("<b>Hello world!</b><br>I am a popup.")
circle.bindPopup("I am a circle.")
polygon.bindPopup("I am a polygon.")
var popup = L.popup()
.setLatLng([51.5, -0.09])
.setContent("I am a standalone popup.")
.openOn(map)
function onMapClick(e) {
popup
.setLatLng(e.latlng)
.setContent("You clicked the map at " + e.latlng.toString())
.openOn(map);
}
map.on('click', onMapClick);
}
}
</script>
<template>
<div id="map"></div>
</template>
<style scoped>
#map {
height: 100vh;
width: 100vw;
}
</style>
结果如下:
7. 加载GeoJSON
这里使用的GeoJSON数据下载自:GeoJSON and KML data for the United States - Eric Celeste (clst.org)
下载地址为:https://eric.clst.org/assets/wiki/uploads/Stuff/gz_2010_us_040_00_20m.json
这里将JSON文件放置于public
目录下
使用Fetch加载GeoJSON并添加到地图:
<script>
import L from 'leaflet'
import 'leaflet/dist/leaflet.css'
export default{
mounted(){
const map = L.map('map').setView([51.505, -0.09], 13)
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 4,
attribution: '© OpenStreetMap'
}).addTo(map)
const marker = L.marker([51.5, -0.09]).addTo(map)
const circle = L.circle([51.508, -0.11], {
color: 'red',
fillColor: '#f03',
fillOpacity: 0.5,
radius: 500000
}).addTo(map)
const polygon = L.polygon([
[51.509, -0.08],
[41.503, -0.06],
[51.51, -10.047]
]).addTo(map)
marker.bindPopup("<b>Hello world!</b><br>I am a popup.")
circle.bindPopup("I am a circle.")
polygon.bindPopup("I am a polygon.")
var popup = L.popup()
.setLatLng([51.5, -0.09])
.setContent("I am a standalone popup.")
.openOn(map)
function onMapClick(e) {
popup
.setLatLng(e.latlng)
.setContent("You clicked the map at " + e.latlng.toString())
.openOn(map);
}
map.on('click', onMapClick);
fetch('/gz_2010_us_040_00_20m.json')
.then(response => response.json())
.then(data => {
console.log(data)
L.geoJSON(data, {
style: {
"color": "#ff7800",
"weight": 5,
"opacity": 0.65
}
}).addTo(map)
});
}
}
</script>
<template>
<div id="map"></div>
</template>
<style scoped>
#map {
height: 100vh;
width: 100vw;
}
</style>
结果如下:
8. 加载WMS服务
参考官方示例:Using WMS and TMS services - Leaflet - 一个交互式地图 JavaScript 库 (leafletjs.cn),添加WMS服务地图:
<script>
import L from 'leaflet'
import 'leaflet/dist/leaflet.css'
export default{
mounted(){
const map = L.map('map').setView([51.505, -0.09], 13)
// L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
// maxZoom: 4,
// attribution: '© OpenStreetMap'
// }).addTo(map)
const marker = L.marker([51.5, -0.09]).addTo(map)
const circle = L.circle([51.508, -0.11], {
color: 'red',
fillColor: '#f03',
fillOpacity: 0.5,
radius: 500000
}).addTo(map)
const polygon = L.polygon([
[51.509, -0.08],
[41.503, -0.06],
[51.51, -10.047]
]).addTo(map)
marker.bindPopup("<b>Hello world!</b><br>I am a popup.")
circle.bindPopup("I am a circle.")
polygon.bindPopup("I am a polygon.")
var popup = L.popup()
.setLatLng([51.5, -0.09])
.setContent("I am a standalone popup.")
.openOn(map)
function onMapClick(e) {
popup
.setLatLng(e.latlng)
.setContent("You clicked the map at " + e.latlng.toString())
.openOn(map);
}
map.on('click', onMapClick);
fetch('/gz_2010_us_040_00_20m.json')
.then(response => response.json())
.then(data => {
console.log(data)
L.geoJSON(data, {
style: {
"color": "#ff7800",
"weight": 5,
"opacity": 0.65
}
}).addTo(map)
});
const wmsLayer = L.tileLayer.wms('http://ows.mundialis.de/services/service?', {
layers: 'SRTM30-Colored-Hillshade',
maxZoom: 4,
}).addTo(map);
}
}
</script>
<template>
<div id="map"></div>
</template>
<style scoped>
#map {
height: 100vh;
width: 100vw;
}
</style>
结果如下:
9. 参考资料
[1]API 参考 | Vue.js (vuejs.org)
[2]Quick Start Guide - Leaflet - a JavaScript library for interactive maps (leafletjs.com)
[3]Quick Start Guide - Leaflet - 一个交互式地图 JavaScript 库 (leafletjs.cn)
[4]Documentation - Leaflet - 一个交互式地图 JavaScript 库 (leafletjs.cn)