Leaflet聚合图层 Leaflet.markercluster 附源码以及中文文档、npm安装教程、Leaflet封装成组件(在摸索中前行)

文章底部附上全部源码

效果(有问题留言)

中文文档 

Leaflet.markercluster 中文文档 V1.5.4_冰樱湛蓝的博客-CSDN博客_leaflet中文文档

官网 

Documentation - Leaflet - 一个交互式地图 JavaScript 库

处理大量的标记

该插件可以处理10,000 甚至 50,000 个标记 (在chrome浏览器下). IE9 在 50,000 数量下会存在一些问题。

 

 如何使用

在你的页面的leaflet库引入处之后,引入本插件的css及js文件。你可以选择如下几种引入方式

  • 使用unpkg的CDN: https://unpkg.com/leaflet.markercluster@1.4.1/dist/
  • 通过npm命令安装: npm install leaflet.markercluster

这里我选择使用npm命令安装

main.js中引入

// 引入 leaflet.markercluster  聚合插件
import "leaflet.markercluster/dist/MarkerCluster.css"
import "leaflet.markercluster/dist/MarkerCluster.Default.css"
import "leaflet.markercluster";

HTML(因为我封装成了组件便于重复使用,所以用了父组件传值来动态设置高度,如不需要自行修改CSS)

<div id="map" :style="'height:'+ mapHeight"></div>

<script>下(为后续生成随机点做准备)

	//生成随机点
	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()
		);
	};

props 接收父组件传参(也包含默认值)

如果只需要聚合 复制如下就够了

mapCenter: { //地图中心点
				type: Object,
				default: () => ({
					lat: 27.982965,
					lng: 120.754488
				})
			},
			mapHeight: { //高度
				type: String,
				default: 'calc(100vh - 50px)'
			},

扩展封装(Marker、多边形、圆形、线)

markerList: { //Marker标记
				type: Array,
				default () {
					return [
						// 	{
						// 	lng: 120.74176311492921,
						// 	lat: 27.97600231947459,
						// 	bindPopup: '芜湖' //点击弹框
						// },
					]
				}
			},
			polygonList: { //多边形绘制
				type: Object,
				default () {
					return {
						bindPopup: '我是多边形多边形多边形!~',
						layerTitle: '多边形', //图层名
						layerType: false, //是否以多图层形式
						latlng: [
							// {
							// 	lng: 120.7526206970215,
							// 	lat: 27.971056199299756,
							// },
							// {
							// 	lng: 120.7683277130127,
							// 	lat: 27.969085268308145,
							// },
							// {
							// 	lng: 120.7559680938720,
							// 	lat: 27.962793209235148,
							// }
						]
					}
				}
			},
			circleList: { //圆形
				type: Object,
				default () {
					return {
						layerTitle: '圆形', //图层名
						layerType: false, //是否以多图层形式
						circle: [
							// 	{
							// 	color: '#000',
							// 	fillColor: '#00b4ff',
							// 	fillOpacity: 0.5, //不透明度
							// 	radius: 500, //半径
							// 	bindPopup: '第一园',
							// 	lat: 27.97164368137987,
							// 	lng: 120.7324504852295
							// }, {
							// 	color: '#fff',
							// 	fillColor: 'red',
							// 	fillOpacity: 0.5, //不透明度
							// 	radius: 500, //半径
							// 	bindPopup: '第二园',
							// 	lat: 27.973860923634668,
							// 	lng: 120.78257560729982
							// },
						]
					}
				}
			},
			lineList: { //线
				type: Object,
				default () {
					return {
						layerTitle: '线', //图层名
						layerType: false, //是否以多图层形式
						circle: [
							/* {
														color: 'red',
														fillOpacity: 0.5, //不透明度
														bindPopup: '第一线',
														latlngs: [
															[27.974865300428114, 120.7456684112549],
															[27.975206407400496, 120.74957370758057],
															[27.976580299561842, 120.75139760971071],
														]
													}, {
														color: '#000',
														fillOpacity: 0.5, //不透明度
														bindPopup: '第二线',
														latlngs: [
															[27.95634915407091, 120.75571060180665],
															[27.95926797966058, 120.77832698822023],
															[27.965560244261578, 120.7740354537964],
														]
													}, */
						]
					}
				}
			}

data(){}

		data() {
			return {

				map: '', //挂载
				mapIconLatlngData: [], //点击生成的经纬度
				dialogVisible: false,
				marker_group: [],
				mapMarkerType: false, //点击生成icon
				LatlngList: [], //循环生成固定icon的经纬度
				
			}
		}

methods()中

以下关键聚合代码

                //生图标模板  再按模板生成多个图标
                var transportIcon = L.Icon.extend({
                    options: {
                        iconSize: ['auto', 24],

                    }
                });
                var carIcon = new transportIcon({
                    iconUrl: require('./logo.png'), //这里图片地址要换成自己本地的
                })
                // 聚合
                var markers = L.markerClusterGroup();

                //生成多个随机点
                for (let i = 0; i < 1000; i++) {

                     //map传入  根据地图中心点随机生成附近经纬度
                    let latlng = getRandomLatLng(map); 

                     //将生成的 latlng 传入聚合
                    markers.addLayer(L.marker(latlng, {
                        icon: carIcon
                    }));
                }

                map.addLayer(markers)//将聚合添加到地图上

整个方法源码(复制可用)这里的方法我用了多图层的形式加载到图层中

initDateNew() {
				const elem = this
				// 初始化地图  状态选项
				console.log(elem.mapCenter, '====')
				var map = L.map('map', {
					// center: [27.973768, 120.73438],
					center: [elem.mapCenter.lat, elem.mapCenter.lng],
					zoom: 14,
					attributionControl: false, // 移除右下角leaflet标识
				});
				// 多个图层切换
				var baseLayers = {
					'高德卫星': L.tileLayer('https://webst01.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}', {
						maxZoom: 18
					}),

					"高德矢量": L.tileLayer.wms(
						'http://wprd04.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}', {
							maxZoom: 18
						}).addTo(map),

					"外网矢量": L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
						maxZoom: 18
					}),

					"腾讯地图": L.tileLayer(
						'http://rt0.map.gtimg.com/realtimerender?z={z}&x={x}&y={-y}&type=vector&style=0', {
							maxZoom: 18
						}),
				};
				//多图层
				var overlays = {
					
				};

				// -----
				//生图标模板  再按模板生成多个图标
				var transportIcon = L.Icon.extend({
					options: {
						iconSize: ['auto', 24],

					}
				});
				var carIcon = new transportIcon({
					iconUrl: require('./logo.png'),
				})
				// 聚合
				var markers = L.markerClusterGroup();
                //生成多个点为
				for (let i = 0; i < 1000; i++) {
					let latlng = getRandomLatLng(map);
					markers.addLayer(L.marker(latlng, {
						icon: carIcon
					}));
				}
				// map.addLayer(markers);
				elem.markerList.forEach(a => {
					L.marker([a.lat, a.lng], {
						icon: carIcon
					}).bindPopup(a.bindPopup).addTo(map)
				})
				//把圆形添加到聚合中  也可注释不需要
				//  添加聚合方式  markers.addLayer(circle)
				var cities3 = L.layerGroup()
				if (elem.circleList.circle.length > 0) {
					elem.circleList.circle.forEach((a, index) => {
						var circle = L.circle([a.lat, a.lng], {
							color: a.color, //边框颜色
							fillColor: a.fillColor, //内部填充颜色
							fillOpacity: a.fillOpacity,
							radius: a.radius
						}).bindPopup(a.bindPopup).on('click', val => {
							map.pm.disableDraw("Polygon");
							// console.log('我都是',val)
							elem.dialogVisible = true
						})
						markers.addLayer(circle)
					})
				
				}
				overlays['聚合'] = markers
				// 
				var bj = L.marker([elem.mapCenter.lat, elem.mapCenter.lng], {
					icon: new L.Icon({
						iconUrl: require('./logo.png'),
						iconSize: ['auto', 28],

					})
				}).bindPopup('中心点');
				// var sh = L.marker([31.213, 121.445]).bindPopup('这里是上海');
				// var gz = L.marker([23.16, 113.23]).bindPopup('这里是广州');
				var cities = L.layerGroup([bj]).addTo(map);
				// -----
				var cities2 = L.layerGroup(); //多边形
				// 多边形绘制 layerType
				if (elem.polygonList.latlng.length > 0) {
					if (elem.polygonList.layerType) {
						var polygon = L.polygon(elem.polygonList.latlng).bindPopup(elem.polygonList.bindPopup).addTo(
							cities2);
						overlays[elem.polygonList.layerTitle] = cities2
					} else {
						var polygon = L.polygon(elem.polygonList.latlng).bindPopup(elem.polygonList.bindPopup).addTo(map)
					}
				}

				// //圆形
				// var cities3 = L.layerGroup()
				// var cities3Circle = []
				// if (elem.circleList.circle.length > 0) {
				// 	elem.circleList.circle.forEach((a, index) => {
				// 		var circle = L.circle([a.lat, a.lng], {
				// 			color: a.color, //边框颜色
				// 			fillColor: a.fillColor, //内部填充颜色
				// 			fillOpacity: a.fillOpacity,
				// 			radius: a.radius
				// 		}).bindPopup(a.bindPopup).on('click', val => {
				// 			map.pm.disableDraw("Polygon");
				// 			// console.log('我都是',val)
				// 			elem.dialogVisible = true
				// 		})
				// 		cities3Circle.push(circle)
				// 	})
				// 	elem.marker_group = new L.layerGroup(cities3Circle).addTo(elem.circleList.layerType ? cities3 : map);

				// 	if (elem.circleList.layerType) {
				// 		overlays[elem.circleList.layerTitle] = cities3
				// 	}
				// }


				// cities3.clearLayers()
				// 创建折线
				var cities4 = L.layerGroup()
				if (elem.lineList.circle.length > 0) {
					elem.lineList.circle.forEach(a => {
						L.polyline(a.latlngs, {
							color: a.color,
							title: a.bindPopup,
						}).bindPopup(a.bindPopup).addTo(elem.lineList.layerType ? cities4 : map);
					})

					if (elem.lineList.layerType) {
						overlays[elem.lineList.layerTitle] = cities4
					}

				}


				var layerControl = L.control.layers(baseLayers, overlays, {
					position: 'bottomright',
					collapsed: false //是否折叠
				}).addTo(map);
				// L.clearLayers()

				// 线
				// removeLayer
				// map.fitBounds(polyline.getBounds());    //将地图的视图设置在给定的矩形地理范围内,地图会自动计算最大缩放级别和中心点
				// var layerControl = L.control.layers(baseLayers, overlays).addTo(map);

				//循环添加多个点
				// elem.LatlngList.forEach((a => {
				// 	L.marker([a.lat, a.lng], {
				// 		icon: new L.Icon({
				// 			className: "lmap-icon",
				// 			iconUrl: require('./logo.png'),
				// iconSize: [24, 24], // 图标尺寸
				// 			iconAnchor:[0,0] // 图标偏移
				// 		}),
				// 		title: '我是一个icon'
				// 	}).addTo(map);
				// }))

				// zoom the map to the polyline
				// console.log(getRandomLatLng(map), '+++++')
				//比列尺
				L.control.scale({
					imperial: false
				}).addTo(map);
				// //单机事件
				map.on('click', i => {
					// 点击获取地图上的经纬度
					// console.log(i, i.latlng.lng, i.latlng.lat)
					var latlng = {
						lng: i.latlng.lng,
						lat: i.latlng.lat
					}
					if (elem.mapMarkerType) {
						//存储点击icon 坐标
						elem.mapIconLatlngData.push(latlng)
						//点击处画icon
						L.marker([i.latlng.lat, i.latlng.lng], {
							icon: new L.Icon({
								className: "lmap-icon",
								iconUrl: require('./logo.png'),
								iconSize: ['auto', 24],
							})
						}).addTo(map);
					}

					//添加弹框
					// L.popup()
					// 	.setLatLng(latlng)
					// 	.setContent('单机弹框')
					// 	.openOn(map);
					// console.log(elem.mapIconLatlngData)
				})
			},

mounted(){}页面渲染后调用方法

		mounted() {
			this.initDateNew(); //正式
		}

右下角的聚合√要打上 

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,以下是一个简单的封装: 首先,需要安装 `leaflet` 和 `leaflet-editable`: ``` npm install leaflet leaflet-editable ``` 然后,创建一个名为 `EditableMap.vue` 的组件: ```html <template> <div ref="mapContainer" class="map-container"></div> </template> <script> import L from 'leaflet' import 'leaflet-editable' export default { name: 'EditableMap', props: { center: { type: Array, required: true }, zoom: { type: Number, default: 13 } }, mounted () { this.map = L.map(this.$refs.mapContainer).setView(this.center, this.zoom) this.map.editTools = new L.Editable(this.map) }, beforeUnmount () { this.map.remove() } } </script> <style scoped> .map-container { height: 400px; } </style> ``` 这个组件会创建一个 Leaflet 地图,并将其设置为可编辑模式。它接受两个 props:`center` 和 `zoom`,分别指定地图的心点和缩放级别。 现在,你可以在你的应用程序使用这个组件了。例如,你可以这样写: ```html <template> <div> <EditableMap :center="[51.505, -0.09]" :zoom="13" /> </div> </template> <script> import EditableMap from '@/components/EditableMap.vue' export default { components: { EditableMap } } </script> ``` 这将在页面上显示一个地图,并将其设置为可编辑模式。你可以使用 Leaflet.Editable API 来添加、编辑和删除图形对象。例如,这是一个在地图上添加圆形的示例: ```js // 获取 EditableMap 组件实例 const editableMap = this.$refs.editableMap.$refs.mapContainer.__vue__ // 创建一个圆形 const circle = L.circle([51.505, -0.09], { radius: 500 }) // 将圆形添加到地图上 editableMap.map.editTools.startCircle(circle) ``` 希望这可以帮助你开始使用 Leaflet.Editable!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值