1.前置知识
- vue3:至少了解过vue3的新特性
- typescript:至少了解过ts的类型声明
- leaflet:了解leaflet基础的使用方法
2.封装原因
使用过leaflet的小伙伴都知道,leaflet和echarts一样有很多的配置项,仅仅是显示一个基础的地图都需要将同样的操作编写多次
<template>
<div id="baseMap" ref="map"></div>
</template>
<script setup lang="ts">
import * as L from 'leaflet@1.9.4'
import 'leaflet/dist/leaflet.css'
import { ref,onMounted } from 'vue@3.3.2'
const map = ref<any>('')// 地图实例
const url = `https://tiles.stadiamaps.com/tiles/stamen_terrain/{z}/{x}/{y}{r}.jpg` //瓦片图地址
const initMap = ()=>{
const bounds = L.latLngBounds(L.latLng(21, 119.54), L.latLng(26, 122)) // 限制地图的拖动范围
const osm = L.tileLayer(url.value, {
maxNativeZoom: 15,
maxZoom: 15
})
map.value = L.map('baseMap', {
center: [23.62788, 120.31094],
zoomControl: false,
zoom: 12,
minZoom: 8,
maxZoom: 15,
attributionControl: false,
layers: [osm],
maxBounds: bounds
})
}
onMounted(()=>{
initMap()
})
</script>
<style lang="less" scoped>
#baseMap{
width:300px;
height:300px;
}
</style>
这样一个基础的地图就显示出来了
但是每一次要使用leaflet创建地图都要将该代码编写一次,造成了代码的冗余,维护性也较差
3.开始封装
现在的需求变成了去掉这些重复的代码,返回给我一个地图实例;这种功能和vueuse中看到的工具函数十分相像;
创建一个useLeaflet.ts
先引入leaflet和leaflet默认样式
import * as L from 'leaflet'
import 'leaflet/dist/leaflet.css'
将冗余的操作都塞进来
export const useLeaflet = ()=>{
const bounds = L.latLngBounds(L.latLng(-90, -180), L.latLng(90, 180))
const osm = L.tileLayer('https://tiles.stadiamaps.com/tiles/stamen_terrain/{z}/{x}/{y}{r}.jpg:', {
maxNativeZoom: 15,
maxZoom: 15
})
return L.map('baseMap', {
center:[23.445, 120.35],
zoomControl:true,
zoom: 13,
minZoom: 0,
maxZoom: 15,
attributionControl: false,
layers: [osm],
maxBounds: bounds
})
}
这样就可以返回一个地图实例;但是既然封装了当然要能复用
- 地图dom的id不能每次都一样,所以作为参数传入,地图的瓦片图和初始中心点可能会有所改变同样作为参数传入
- 每次都要在onMounted生命周期中调用,onBeforeUnmount中销毁,何不在工具中完成,在工具中调用创建地图实例并返回一个ref对象
- 最终代码如下
import * as L from 'leaflet'
import 'leaflet/dist/leaflet.css'
import {onMounted,onBeforeUnmount,ref} from 'vue'
export const useLeaflet = (mapId: string,url: string,center: [number, number],)=>{
const mapRef = ref() //地图实例
const bounds = L.latLngBounds(L.latLng(-90, -180), L.latLng(90, 180))
const osm = L.tileLayer(url, {
maxNativeZoom: 15,
maxZoom: 15
})
onMounted(() => {
mapRef.value = L.map(mapId, {
center,
zoomControl:true,
zoom: 13,
minZoom: 0,
maxZoom: 15,
attributionControl: false,
layers: [osm],
maxBounds: bounds
})
}
/** 卸载地图 */
onBeforeUnmount(() => {
mapRef.value.remove()
})
return { mapRef}
}
在vue组件中调用
<template>
<div id="baseMap" class="w-full h-full"></div>
</template>
<script setup lang="ts">
import { useLeaflet } from '@/hooks'
const { mapRef } = useLeaflet(
'baseMap',
'https://tiles.stadiamaps.com/tiles/stamen_terrain/{z}/{x}/{y}{r}.jpg',
[23.445, 120.35],
{
miniMap: {
show: true,
position: 'topright'
}
}
)
</script>
地图正常显示,且可以使用mapRef对地图进行操作
4.扩展
可以根据需求在初始化时对地图的配置进行修改,在useLeaflet函数添加第四个参数options,例如
/** options的类型约束 */
export type LeafletOptionsType = {
showZoom?: boolean
showScale?: boolean
miniMap?: {
show?: boolean
position?: 'bottomleft' | 'bottomright' | 'topleft' | 'topright'
}
}
export const useLeaflet = (
mapId: string,
url: string,
center: [number, number],
options?: LeafletOptionsType
) => {}
本次给大家带来的内容就这么多,我的文章对您有用的话可以给笔者一个小小的赞,我会为大家带来更多的使用技巧,谢谢支持