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>
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。