基于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

如果顺利的话,打开网址,将会看到一个欢迎界面:

image-20220823104934305

接下来将模板中无用的文件与代码删除

删除初始的组件:

image-20220823105254154

清空App.vue

image-20220823105453658

新建一个底图组件Map.vue

image-20220823105904539

App.vue中引入Map:

<script setup>
	import Map from './components/Map.vue'
</script>

<template>
	<Map></Map>
</template>

<style scoped>
</style>

至此环境准备完成,不妨测试一下,顺利的话将会出现test字样

可选项,设置全局样式,将main.css中边距和填充设置为0:

image-20220823111225375

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>

结果如下:

image-20220823111544263

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>

结果如下:

image-20220823112606601

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>

结果如下:

image-20220823113320328

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>

结果如下:

image-20220823113630415

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>

结果如下:

image-20220824001300569

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>

结果如下:

image-20220824001849518

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)

posted @ 2022-08-24 00:23  当时明月在曾照彩云归  阅读(9716)  评论(0编辑  收藏  举报