乐于分享
好东西不私藏

uniapp微信小程序地图多地点标记组件

uniapp微信小程序地图多地点标记组件

uniapp小程序应用中实现多商户或者用户等多地点地图标记组件,基于腾讯地图实现地图放大缩小,中心点移动都可以获取范围内的标记点,该组件简单实用。

已关注

关注

重播 分享

一、功能
获取腾讯地图,获取当前定位

实现地图上多点气泡标记,根据不同的中心点(视野发生变化)显示范围内的数据并标记出来
地图放大缩小
返回到当前定位
选中标记,显示标记信息
二、代码
1、首先引用地图组件,获取地图,定义地图属性值
如下代码:
<map class="map" id="map" :show-location="true" theme="satellite" :markers="listMarkers" :scale="state.scale" :latitude="state.latitude" :longitude="state.longitude" :min-scale="state.minScale" @regionchange="mapRegionchange" @callouttap="markertap"@markertap="markertap"> </map>
const state = reactive({// 默认位置坐标-或者获取当前设备的坐标赋值latitude28.668148//初始默认中心纬度longitude115.866537//初始默认中心经度scale13//初始缩放大小 数字越小 显示的范围越大,数字越大显示的范围越少 最大18minScale4.5//最小缩放级别// 地图标点markers: [],// 列表标记点数据listMarkers: [],	});  //地图属性
2、实现地图的操作:放大缩小,返回当前位置
在地图上添加操作按钮:
<!--地图操作按钮--><viewclass="map-btn"><!-- 按钮-返回原位 --><viewclass="tool-btn" @tap="toLocation"><textclass="nvue-iconfont mapico">&#xec32;</text></view><!-- 按钮-放大 --><viewclass="tool-btn" @tap="mapScaleUp"><textclass="nvue-iconfont mapico">&#xec13;</text></view><!-- 按钮-缩小 --><viewclass="tool-btn" @tap="mapScaleDown"><textclass="nvue-iconfont mapico">&#xe6e3;</text></view></view>
实现操作地图的方法:
// 回到原位/我的位置,恢复默认缩放const toLocation = () => {//移动到当前的坐标		_mapContext.value.moveToLocation({longitude: myLocation.value.longitude,latitude: myLocation.value.latitude		});	};// 放大地图const mapScaleUp = () => {updateMapScale(1);	};// 缩小地图const mapScaleDown = () => {updateMapScale(2);	};//设置地图缩放等级const updateMapScale = (type = 0, level = 15) => {		_mapContext.value.getScale({successres => {				state.scale = res.scale;nextTick(() => {// 指定缩放级别if (type == 0) {						state.scale = level					}// 放大else if (type == 1 && state.scale < 20) {						state.scale = state.scale + 1 > 20 ? 20 : state.scale + 1					}// 缩小else if (type == 2 && state.scale > state.minScale) {						state.scale = state.scale - 1 < state.minScale ? state.minScale : state							.scale - 1					}				})			}		})	};
如图:

3、地图标记点实现
可从后端获取带有地图坐标的地点信息列表,然后赋值到地图中(markers)的属性上,可以根据实际需求更改气泡的样式等,如代码需要的地点属性:
{id:1,longitude:'115.851002'//经度latitude:'28.689684',//纬度iconPath:'/static/ad/ad01.jpg',//缩略图width:40,height40title:'商家1',address:'商家标记地址1',alpha1,   //透明度callout: {  //自定义标记点上方的气泡窗口 点击有效 content'商家标记点1',//文本 color'#ffffff',//文字颜色 fontSize12,//文本大小 borderRadius5,//边框圆角 padding:7, bgColor'#ff6100',//背景颜色 display'ALWAYS',//常显 },}
效果图:
4、选中地图上的点
地图组件自带了@markertap 点击标记点时触发 和 @callouttap 点击标记点对应的气泡时触发两个方法,可实现点击标记获取选中标记的信息:
// 点击地图marker点const markertap = (e) => {//获取选中的信息const value = listMarkers.value.find(item => item.id == e.detail.markerId); //查找符合的信息chooseItemInfo.value = value;emits("chooseMarker", value); //传输通知给父组件};
<!--选中的信息底部漂浮框--><viewclass="info-view"v-if="chooseItemInfo.id"><viewclass="iv-item"><imageclass="ivi-img":src="chooseItemInfo.iconPath"mode="widthFix" /><viewclass="ivi-text"><textclass="ivi-t-title">{{ chooseItemInfo.title }}</text><textclass="ivi-t-address">{{ chooseItemInfo.address }}</text></view></view></view>

5、地图视野发生变化时,显示当前视野内的标记点

也是使用了地图组件自带的@regionchange 视野发生变化时触发,实现地图视野发生变化时,显示当前视野内的标记点
// 地图视野发生变化const mapRegionchange = (e) => {// console.log(e,"视野发生变化时触发",_mapContext.value.getCenterLocation());		chooseItemInfo.value = {};//移动结束时 加载范围内的列表的数据if (e.type === "end") {//地图移动结束后 获取中心的的坐标(可发送给后台处理 获取范围内的数据,更新标记)			_mapContext.value.getCenterLocation({success(res) {//获取移动结束时的const latitude = res.latitudeconst longitude = res.longitudeif ((state.longitude - longitude) < 0.000005 && (state.longitude - longitude) > 0 &&						latitude == state.latitude) { // 对静态移动标点做限制防止偏移return					}emits("moveMapView", res); //传输移动到的中心坐标// console.log('地图视野变化');					state.latitude = res.latitude;					state.longitude = res.longitude;// nextTick(() => {// 	getList();// })				}			})		}	};

可根据实际业务对该地图进行开发,官方文档:
https://uniapp.dcloud.net.cn/component/map.html
下面贴上示例代码,予以参考:
组件:
<template><!--腾讯地图多标记点组件--><viewclass="map-box"><!--地图主体--><viewclass="map-viw"><mapclass="map"id="map":show-location="true"theme="satellite":markers="listMarkers":scale="state.scale" :latitude="state.latitude" :longitude="state.longitude" :min-scale="state.minScale"				@regionchange="mapRegionchange" @callouttap="markertap" @markertap="markertap"></map></view><!--地图操作按钮--><viewclass="map-btn"><!-- 按钮-返回原位 --><viewclass="tool-btn" @tap="toLocation"><textclass="nvue-iconfont mapico">&#xec32;</text></view><!-- 按钮-放大 --><viewclass="tool-btn" @tap="mapScaleUp"><textclass="nvue-iconfont mapico">&#xec13;</text></view><!-- 按钮-缩小 --><viewclass="tool-btn" @tap="mapScaleDown"><textclass="nvue-iconfont mapico">&#xe6e3;</text></view></view><!--选中的信息底部漂浮框--><viewclass="info-view"v-if="chooseItemInfo.id"><viewclass="iv-item"><imageclass="ivi-img":src="chooseItemInfo.iconPath"mode="widthFix" /><viewclass="ivi-text"><textclass="ivi-t-title">{{ chooseItemInfo.title }}</text><textclass="ivi-t-address">{{ chooseItemInfo.address }}</text></view></view></view></view></template><scriptsetup>import {		ref,		reactive,		nextTick,		getCurrentInstance,		watchfrom 'vue'import {		onReadyfrom "@dcloudio/uni-app";//宏命令-自动暴露声明const props = defineProps({markersArr: {typeArray,default:()=>{return []},		}, //标记点列表myLcat: {typeObject,default()=>{return {}}		}, //我的位置	});const _mapContext = ref(null); //地图对象onReady(() => {console.log("onReady");		_mapContext.value = uni.createMapContext('map',getCurrentInstance()); //getCurrentInstance为当前的组件实例对象,如vue2中的this	});const listMarkers = ref(props.markersArr); //地图标记点const chooseItemInfo = ref({}); //点击mark选中的信息const myLocation = ref(props.myLcat); //我的中心点位置const state = reactive({// 默认位置坐标-或者获取当前设备的坐标赋值latitude28.668148//初始默认中心纬度longitude115.866537//初始默认中心经度scale13//初始缩放大小 数字越小 显示的范围越大,数字越大显示的范围越少 最大18minScale4.5//最小缩放级别// 地图标点markers: [],// 列表标记点数据listMarkers: [],	});  //地图属性//监听标记数据的变化const mr = watch(() => props.markersArr(newVal) => {// console.log(newVal,"数据")		listMarkers.value = newVal;	}, {immediatetrue // 立即执行初始化	})//监听我的位置变化const mc = watch(() => props.myLcat(newVal) => {// console.log(newVal,"数据");		myLocation.value = newVal;	}, {immediatetrue // 立即执行初始化	});const emits = defineEmits(["moveMapView""chooseMarker"]); //子组件触发通知给父组件的函数方法 地图移动 选中Makers标点// 点击地图marker点const markertap = (e) => {// console.log(e,"点击了marker 点")//获取选中的信息const value = listMarkers.value.find(item => item.id == e.detail.markerId); //查找符合的信息		chooseItemInfo.value = value;emits("chooseMarker", value); //传输通知给父组件	};// 回到原位/我的位置,恢复默认缩放const toLocation = () => {//移动到当前的坐标		_mapContext.value.moveToLocation({longitude: myLocation.value.longitude,latitude: myLocation.value.latitude		});	};// 放大地图const mapScaleUp = () => {updateMapScale(1);	};// 缩小地图const mapScaleDown = () => {updateMapScale(2);	};//设置地图缩放等级const updateMapScale = (type = 0, level = 15) => {		_mapContext.value.getScale({successres => {				state.scale = res.scale;nextTick(() => {// 指定缩放级别if (type == 0) {						state.scale = level					}// 放大else if (type == 1 && state.scale < 20) {						state.scale = state.scale + 1 > 20 ? 20 : state.scale + 1					}// 缩小else if (type == 2 && state.scale > state.minScale) {						state.scale = state.scale - 1 < state.minScale ? state.minScale : state							.scale - 1					}				})			}		})	};// 地图视野发生变化const mapRegionchange = (e) => {// console.log(e,"视野发生变化时触发",_mapContext.value.getCenterLocation());		chooseItemInfo.value = {};//移动结束时 加载范围内的列表的数据if (e.type === "end") {//地图移动结束后 获取中心的的坐标(可发送给后台处理 获取范围内的数据,更新标记)			_mapContext.value.getCenterLocation({success(res) {//获取移动结束时的const latitude = res.latitudeconst longitude = res.longitudeif ((state.longitude - longitude) < 0.000005 && (state.longitude - longitude) > 0 &&						latitude == state.latitude) { // 对静态移动标点做限制防止偏移return					}emits("moveMapView", res); //传输移动到的中心坐标// console.log('地图视野变化');					state.latitude = res.latitude;					state.longitude = res.longitude;// nextTick(() => {// 	getList();// })				}			})		}	};</script><stylelang="scss">@font-face {font-family'mapico';srcurl('./iconfont.ttf'format('truetype');	}/**ioc 图标**/.mapico {font-family: mapico;/* font-size: 70upx; */	}.map-box {width100vw;height100vh;overflow: hidden;display: flex;flex-direction: column;.map-viw {width100%;height100%;flex2;display: flex;flex-direction: column;overflow: hidden;.map {width100%;height100%;position: relative;			}		}		// 右侧按钮组.map-btn {width70rpx;height70rpx;position: fixed;right30rpx;top50rpx;.tool-btn {background-color#ffffff;border-radius10rpx;width70rpx;height70rpx;align-items: center;justify-content: center;box-shadow0 0 8px #ccc;margin-bottom20rpx;.nvue-iconfont {display: block;position: relative;text-align: center;line-height76rpx;color#333;font-size44rpx;				}			}		}		//信息.info-view {position: absolute;z-index2;width100%;height140rpx;bottom100rpx;left0;display: flex;justify-content: center;.iv-item {width80%;background-color#ffffff;padding10rpx;height100%;border-radius10rpx;display: flex;flex-direction: row;align-items: center;.ivi-img {padding10rpx;width120rpx;height120rpx;				}.ivi-text {flex2;display: flex;flex-direction: column;.ivi-t-title {font-size1rem;font-weight: bold;color#333;					}.ivi-t-address {font-size0.8rem;color#999;					}				}			}		}	}</style>
引用组件,所使用测试数据为静态数据
<template><!--腾讯地图插件--><mapViewv-if="isShow":markersArr="markerArr":myLcat="myLocation"  @chooseMarker="getChooseMarker" @moveMapView="getMapCenterLoca"></mapView></template><scriptsetup>import { nextTick, onMounted, ref } from 'vue';import mapView from '@/components/map/map.vue'const markerArr = ref([]);//标记点,可动态获取const isShow = ref(false);//const myLocation = ref({});//用户发送到后台请求对应的数据onMounted(()=>{getMapMarkersList();nextTick(()=>{			isShow.value = true;		})getMyLocation();	});//获取地图移动的中心坐标const getMapCenterLoca = (e)=>{console.log("中心坐标:",e);	};//获取选中的标记const getChooseMarker = (e) =>{console.log("选中的气泡标记:",e);	};//获取当前所在的位置const getMyLocation =()=>{//获得当前的位置		uni.getLocation({type'gcj02'//返回国测局坐标success(e) {console.log(e,"我的位置")				myLocation.value = e;			},fail(e) {console.log('失败', e);			}		})	}//获取位置中心范围内的数据const getMapMarkersList = () =>{// markerArr.value = [];	markerArr.value =	[			{id:1,longitude:'115.851002'//经度latitude:'28.689684',//纬度iconPath:'/static/ad/ad01.jpg',//缩略图width:40,height40title:'商家1',address:'商家标记地址1',alpha1,   //透明度callout: {  //自定义标记点上方的气泡窗口 点击有效content'商家标记点1',//文本color'#ffffff',//文字颜色fontSize12,//文本大小borderRadius5,//边框圆角padding:7,bgColor'#ff6100',//背景颜色display'ALWAYS',//常显				},			},			{id:2,longitude:'115.880356'latitude:'28.643896',iconPath:'/static/ad/ad02.jpg',width:40,height40title:'商家2',address:'商家标记地址2',alpha1,  callout: {  //气泡窗口 content:'商家标记点2',color'#ffffff',fontSize12,borderRadius5,padding:7,bgColor'#ffaa00',display'ALWAYS',				},			},			{id:3,longitude:'115.902672'latitude:'28.671311',iconPath:'/static/ad/ad03.jpg',width:40,height40title:'商家3',address:'商家标记地址3',alpha1,callout: {  //气泡窗口 content'商家标记点3',color'#ffffff',fontSize12,borderRadius5,padding:7,bgColor'#3f94fd',display'ALWAYS',				},			},			{id:4,longitude:'115.881386',latitude:'28.682456',iconPath:'/static/ad/ad02.jpg',width:40,height40,title:'商家4',address:'商家标记地址4',alpha1,callout: {  //气泡窗口 content'商家标记点4',color'#000000',fontSize12,borderRadius5,padding:7,bgColor'#00ff00',display'ALWAYS',				},			},			{id:5,longitude:'115.854435',latitude:'28.677787',iconPath:'/static/ad/ad01.jpg',width:40,height40title:'商家5',address:'商家标记地址5',alpha1,callout: {  //气泡窗口 content'商家标记点5',color'#ffffff',fontSize12,borderRadius5,padding:7,bgColor'#3f94fd',display'ALWAYS',				},			},			{id:6,longitude:'115.848255',latitude:'28.660617',iconPath:'/static/ad/ad02.jpg',width:40,height40title:'商家6',address:'商家标记地址6',alpha1,callout: {  //气泡窗口 content'商家标记点6',color'#3f94fd',fontSize12,borderRadius5,padding:7,bgColor'#ffffff',display'ALWAYS',				},			},			{id:7,longitude:'115.849972',latitude:'28.670407',iconPath:'/static/ad/ad03.jpg',width:40,height40title:'商家7',address:'商家标记地址7',alpha1,callout: {  //气泡窗口 content'商家标记点7',color'#ffffff',fontSize12,borderRadius5,padding:7,bgColor'#3f94fd',display'ALWAYS',				},			},			{id:8,longitude:'115.900612',latitude:'28.661671',iconPath:'/static/ad/ad01.jpg',width:40,height40title:'商家8',address:'商家标记地址8',alpha1,callout: {  //气泡窗口 content'商家标记点8',color'#ffffff',fontSize12,borderRadius5,padding:7,bgColor'#3f94fd',display'ALWAYS',				},			},		];	}</script><style></style>