hint:
node => 14.17.5
npm => 6.14.14
抉择装置leaflet版本 '^1.7.1'
以实现散点图的业务为驱动
Map的承载Div
<template> <div id="myMap2" class="mainMap2"></div></template>
初始化地图并且实现了几个繁难性能点:
- 依据数个点位生成polygon并加载
- 随机点位加载svg标记点
- 加载标记点后从新设置标记点大小色彩再次重绘
<script>import 'leaflet/dist/leaflet.css'import L from 'leaflet'import {addPloygon,addScatterPointIcon2,newScatterStyle} from "@/utils/layers"import { onMounted,} from 'vue'export default { name: 'Map', props: { }, setup(props, context) { console.log(props,context); let mapMap = null let scatterLayerGroup = L.featureGroup() onMounted(()=>{ initMap() addPloygon([[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04],[35, -122.04]]).addTo(mapMap) }) //获取以后可是方位随机点位的经纬度 const getRandomLatLng = map => { let bounds = map.getBounds(), southWest = bounds.getSouthWest(), northEast = bounds.getNorthEast(), lngSpan = northEast.lng - southWest.lng, latSpan = northEast.lat - southWest.lat; return L.latLng( southWest.lat + latSpan * Math.random(), southWest.lng + lngSpan * Math.random() ); }; const initMap = () =>{ console.log('初始化地图'); //天地图 const image = L.tileLayer('http://t{s}.tianditu.gov.cn/img_w/wmts?tk=bb11a33c4377f10603478ed166691455&SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TileMatrix={z}&TileCol={x}&TileRow={y}', { subdomains: [0, 1, 2, 3, 4, 5, 6, 7], }) //注记 const cia = L.tileLayer('http://t{s}.tianditu.gov.cn/cia_w/wmts?tk=bb11a33c4377f10603478ed166691455&SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cia&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TileMatrix={z}&TileCol={x}&TileRow={y}', { subdomains: [0, 1, 2, 3, 4, 5, 6, 7], transparent: true, zIndex: 3, }) //天地图图组 const tiandiMap = L.layerGroup([image, cia]); let myCenter = [31.95723698714103, 104.29901249999988]; // 设置地图核心 mapMap = L.map('myMap2',{ center: myCenter, minZoom:1, layers: [tiandiMap], zoom: 3 }) let initSiteLatlon = getRandomLatLng(mapMap) scatterLayerGroup.addLayer(addScatterPointIcon2(initSiteLatlon)) scatterLayerGroup.addTo(mapMap); } const changeStyle = (val,scatterRadius) =>{ let newStyle = newScatterStyle(val.color,scatterRadius.value,false) scatterLayerGroup.eachLayer(function (layer) { layer.setIcon(newStyle) }); } return { changeStyle } }}</script>
这是封装的layer生成模块=>layers.js"leaflet.markercluster": "^1.5.0",
import L from 'leaflet'/** * add polygon * @param {*} latlngs */export function addPloygon (latlngs ) { var layer = L.polygon(latlngs , {color: 'rgb(80,227,194)'}) return layer}/** * add scatterPoint * @param {*} latlngs */ export function addScatterPoint (latlng) { let circleMarker = L.circle(latlng,{ radius:800000, fillColor:'red', fillOpacity:'1', color: 'red', //色彩 }) circleMarker.on('mouseover',function(){ circleMarker.bindPopup(`<p>Hello world!<br />This is a nice popup.</p>`).openPopup(); }) circleMarker.on('mouseout', function(){ circleMarker.closePopup() }); return circleMarker}/** * add scatterPoint VIP * @param {*} latlngs 点经纬度 */ export function addScatterPointIcon2 (latlng) { var iconSettings = { mapIconUrl: '<svg version="1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 149 178"><path fill="{mapIconColor}" stroke="#FFF" stroke-width="6" stroke-miterlimit="30" d="M126 23l-6-6A69 69 0 0 0 74 1a69 69 0 0 0-51 22A70 70 0 0 0 1 74c0 21 7 38 22 52l43 47c6 6 11 6 16 0l48-51c12-13 18-29 18-48 0-20-8-37-22-51z"/><circle fill="{mapIconColorInnerCircle}" cx="74" cy="75" r="61"/><circle fill="#FFF" cx="74" cy="75" r="{pinInnerCircleRadius}"/><image x="34" y="35" width="80" height="80" xlink:href="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fwww.51tfb.com%2Fuploadfile%2F20190316%2F201903160950595c8c568363cdc.jpg&refer=http%3A%2F%2Fwww.51tfb.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1633143290&t=bf91e17fa94f787ffafaa729eb843a6f"/></svg>', mapIconColor: 'red', mapIconColorInnerCircle: '#fff', pinInnerCircleRadius:48 }; var divIcon = L.divIcon({ className: "leaflet-data-marker", html: L.Util.template(iconSettings.mapIconUrl, iconSettings), //.replace('#','%23'), iconAnchor : [12, 32], iconSize : [30, 30], popupAnchor : [0, -28] }); var marker = L.marker(latlng, { icon: divIcon, id: 'scatter' }); return marker}/** * new scatterPoint style * marker.setIcon(newScatterStyle); * @param {*} color 色彩 * @param {*} radius 半径 * @param {*} isVip 是否是vip */ export function newScatterStyle (color,radius,isVip) { var iconSettings if(isVip){ iconSettings = { mapIconUrl: '<svg version="1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 149 178"><path fill="{mapIconColor}" stroke="#FFF" stroke-width="6" stroke-miterlimit="30" d="M126 23l-6-6A69 69 0 0 0 74 1a69 69 0 0 0-51 22A70 70 0 0 0 1 74c0 21 7 38 22 52l43 47c6 6 11 6 16 0l48-51c12-13 18-29 18-48 0-20-8-37-22-51z"/><circle fill="{mapIconColorInnerCircle}" cx="74" cy="75" r="61"/><circle fill="#FFF" cx="74" cy="75" r="{pinInnerCircleRadius}"/><image x="34" y="35" width="80" height="80" xlink:href="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fwww.51tfb.com%2Fuploadfile%2F20190316%2F201903160950595c8c568363cdc.jpg&refer=http%3A%2F%2Fwww.51tfb.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1633143290&t=bf91e17fa94f787ffafaa729eb843a6f"/></svg>', mapIconColor: color, mapIconColorInnerCircle: '#fff', pinInnerCircleRadius:61 }; }else{ iconSettings = { mapIconUrl: '<svg version="1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 149 178"><path fill="{mapIconColor}" stroke="#FFF" stroke-width="6" stroke-miterlimit="30" d="M126 23l-6-6A69 69 0 0 0 74 1a69 69 0 0 0-51 22A70 70 0 0 0 1 74c0 21 7 38 22 52l43 47c6 6 11 6 16 0l48-51c12-13 18-29 18-48 0-20-8-37-22-51z"/></svg>', mapIconColor: color, mapIconColorInnerCircle: '#fff', pinInnerCircleRadius:61 }; } var divIcon = L.divIcon({ className: "leaflet-data-marker", html: L.Util.template(iconSettings.mapIconUrl, iconSettings), //.replace('#','%23'), iconAnchor : [12, 32], iconSize : [radius, radius], popupAnchor : [0, -28] }); return divIcon}
总结:以前都是用的supermap的leaflet库,首次用vue3.0配合原生leaflet。目标也是为了去相熟原生leaflet的文档,不得不说他的文档写的很不错,比openlayer好很多。学习中成长吧,为初学者留下一点案例材料。
原作者地址:https://segmentfault.com/u/yo...
上面补充一下聚合图的实例
<template> <div> <p>32</p> <div id="myMap2" class="mainMap2"></div> </div></template><script>import 'leaflet/dist/leaflet.css'import L from 'leaflet'import "leaflet.markercluster/dist/MarkerCluster.css"import "leaflet.markercluster/dist/MarkerCluster.Default.css"import "leaflet.markercluster";//定义markar款式import icon from "leaflet/dist/images/marker-icon.png";import iconShadow from "leaflet/dist/images/marker-shadow.png";let DefaultIcon = L.icon({ iconUrl: icon, shadowUrl: iconShadow});L.Marker.prototype.options.icon = DefaultIcon;import { onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted, onRenderTracked, onRenderTriggered, watch, computed} from 'vue'export default { name: 'HelloWorld', props: { msg: String, }, setup(props, context) { console.log(props,context); let mapMap = null console.log('这里的setup函数执行就相当于vue2的钩子beforeCreate和created') onBeforeMount(()=>{ console.log('setup的钩子和vue2.0的钩子同时存在的时候,setup里的钩子会先执行') }) onMounted(()=>{ initMap() console.log('渲染完了') }) const getRandomLatLng = map => { let bounds = map.getBounds(), southWest = bounds.getSouthWest(), northEast = bounds.getNorthEast(), lngSpan = northEast.lng - southWest.lng, latSpan = northEast.lat - southWest.lat; return L.latLng( southWest.lat + latSpan * Math.random(), southWest.lng + lngSpan * Math.random() ); }; const createMakerByLatlng = (latlng, options) => { return L.marker(latlng, options); }; const createMakerCluster = () => { return L.markerClusterGroup(); }; const initMap = () =>{ console.log('初始化地图'); //天地图 const image = L.tileLayer('http://t{s}.tianditu.gov.cn/img_w/wmts?tk=bb11a33c4377f10603478ed166691455&SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TileMatrix={z}&TileCol={x}&TileRow={y}', { subdomains: [0, 1, 2, 3, 4, 5, 6, 7], }) //注记 const cia = L.tileLayer('http://t{s}.tianditu.gov.cn/cia_w/wmts?tk=bb11a33c4377f10603478ed166691455&SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cia&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TileMatrix={z}&TileCol={x}&TileRow={y}', { subdomains: [0, 1, 2, 3, 4, 5, 6, 7], transparent: true, zIndex: 3, }) //天地图图组 const tiandiMap = L.layerGroup([image, cia, ]); let myCenter = [31.95723698714103, 104.29901249999988]; // 设置地图核心 mapMap = L.map('myMap2',{ center: myCenter, layers: [tiandiMap], zoom: 1 }) console.log(3); console.log(mapMap); let cluster = createMakerCluster(); for (let i = 0; i < 10000; i++) { let latlng = getRandomLatLng(mapMap); let maker = createMakerByLatlng(latlng); cluster.addLayer(maker); } mapMap.addLayer(cluster); } onBeforeUpdate(()=>{ console.log('更新前') }) onUpdated(()=>{ console.log('更新后') }) onBeforeUnmount(()=>{ console.log('卸载前:vue3.0的这个生命周期命名要区别于vue2.0的beforeDestroy') }) onUnmounted(()=>{ console.log('卸载后:vue3.0的这个生命周期命名要区别于vue2.0的destroyed') }) onRenderTracked((event) => { console.log(event); console.log('新增的钩子状态跟踪函数(跟踪全副的,须要本人去查看哪个变动了):其实就是跟踪return 里数据的变动') }) onRenderTriggered(event => { console.log(event); console.log('新增的钩子状态跟踪函数(区别在与准确跟踪变动的那个数据') }) watch(props.msg, (val, oldVal) => { console.log(val, oldVal); }) return { } }}</script><style>.mainMap2{ width: 900px; height: 900px; border: 2px solid red;}</style>