最近需要在小程序中做一个点位图,用于展示不同点位,且根据地图不同的缩放级别,实现多点位的聚合和分裂效果,使用uniapp提供的map组件,官方文档

实现效果:

代码如下:

  1. 使用地图组件,需要初始化经纬度

       <map 
			id="map" 
			style="width: 100%; height: 100vh;" 
			latitude="39.904989" 
			longitude="116.405285"
			:show-location="true"
			:scale="mapScale"
			:max-scale="19"
			@markertap="bindMarkerTap"
		></map>

2. 授权获取用户位置信息

2.1 用户授权

getAuthSetting() {
                // 获取用户的授权信息
				let authSetting = this.$store.state.authSetting
				// 判断用户是否授权
				if(!authSetting['scope.userLocation']) {
					// 如果没有授权,则调起授权面板
					uni.authorize({
						scope:"scope.userLocation",
						success: () => {
                            // 用户同意授权后,获取用户位置信息
							this.getUserLocation()
						},
						fail() {
							// 用户拒绝授权,弹框提示
							uni.showModal({
								title: '提示',
								content: '若点击不授权,将无法使用位置功能',
								cancelText: '不授权',
								cancelColor: '#999',
								confirmText: '授权',
								confirmColor: '#f94218',
								success: (resp) => {
									if(resp.confirm) {
										// 选择弹框内授权,调起设置界面进行授权
										uni.openSetting({
											success: (resp) => {
                                                // 授权信息保存在vuex中
												this.$store.commit('setAuthSetting',resp.authSetting)
                                                // 授权成功后,获取用户位置信息
												this.getUserLocation()
											}
										})
										
									}else if(resp.cancel) {
										 // 选择弹框内 不授权
										uni.showToast({
											title: '无法获取位置信息,请去授权',
											icon: 'none'
										})
									}
								}
							})
						}
					})
				}else {
                    // 用户已授权,则直接获取位置信息
					this.getUserLocation()
				}
}

3.  获取用户位置信息,uniapp的api `uni.getLocation` 在小程序中只能获取到用户的经纬度,我这里需要使用用户的详细地址,所以使用了腾讯地图的api ,在腾讯位置服务平台申请key值,下载sdk包

3.1 导入腾讯地图位置服务sdk包

import QQMapWX from "../../static/js/qqmap-wx-jssdk.min.js";
// 获取腾讯地图api
let qqmapsdk = new QQMapWX({ key: "你自己申请的key" });

3.2 获取用户当前经纬度以及详细地址

getUserLocation() {
				uni.getLocation({
					type: "gcj02",
					success:(res) => {
						console.log('当前位置的经度:' + res.longitude);
						console.log('当前位置的纬度:' + res.latitude);
                        const location = {
                            latitude: res.latitude,
                            longitude: res.longitude
                        }
						let data = {}
                        // 调用腾讯地图api,获取用户详细地址
						qqmapsdk.reverseGeocoder({
						    location,
						    success: res => {
								data = {
									...location,
									address: res.result.address_component.city
								}
                                // 用户经纬度和详细地址保存到vuex中
								this.$store.commit('setUserAddress',data)
								// 调用渲染地图的函数
                                this.createMapContext()
							},
							fail: error => {
								console.log('err',error)
							}
						})
						
					},
					fail: (error) => {
						uni.showToast({
							title: '获取位置信息失败!',
							icon: 'none',
							success: function(res) {
								this.$store.commit('setAuthSetting',{'scope.userLocation': false})
							}
						})
					}
				})
    }

4. 渲染地图

4.1 初始化地图,创建点聚合,api文档

createMapContext() {
				// 创建地图对象
				this._mapContext = uni.createMapContext("map", this);
				 // 仅调用初始化,才会触发 on.("markerClusterCreate", (e) => {})
				this._mapContext.initMarkerCluster({ // 初始化点聚合的配置
				        enableDefaultStyle: false, // 是否使用默认样式
				        zoomOnClick: true,
				        gridSize: 60,
				        complete(res) {
				          console.log('initMarkerCluster', res)
				        }
				});
				
				// 新的聚合簇产生时触发
				this._mapContext.on("markerClusterCreate", (e) => {
							let clusterMarkers = []
							const clusters = e.clusters // 新产生的聚合簇
							 clusters.forEach((cluster,index) => {
								const {
									center, // 聚合点的经纬度数组
									clusterId, // 聚合簇id
									markerIds // 已经聚合了的标记点id数组
								} = cluster
								let clusterObj = {
									clusterId, //必须
									...center,
									width: 0,
									height: 0,
									iconPath: '',
									label: {// 定制聚合簇样式
										content: markerIds.length + '',
										fontSize: 16,
										color: '#fff',
										width: 50,
										height: 50,
										bgColor: '#419afcD9',
										borderRadius: 25,
										textAlign: 'center',
										anchorX: -10,
										anchorY: -35,
										
									}
								}
								clusterMarkers.push(clusterObj)
							})
						    // 添加聚合簇
						    this._mapContext.addMarkers({
							    markers:clusterMarkers,
							    clear: false, //是否先清空地图上所有的marker
						    })
				});	

	}

4.2 获取点标记的经纬度,初始化添加所有点标记

        // 调接口获取所有点标记经纬度
        // 添加点标记
        addMarkers() {
			    let markers = []
			    let iconPath = ''
			    this.markersOptions.forEach((item,index) => {
                    //根据点位类型不同,定义不同的标记icon
			    	switch(item.type) {
			    	      case 1:
			    	      iconPath = '../../static/school-point.png'
			    	      break;
			    	      case 2:
			    	      iconPath = '../../static/hospital-point.png'
			    	      break;
			    	      case 3:
			    	      iconPath = '../../static/company-point.png'
			    	      break;
			    	      case 4:
			    	      iconPath = '../../static/other- point.png'
			    	}
					let markerObj = {
						width: 45,
						height: 45,
						id: item.id,
						iconPath,
						latitude: Number(item.lat),
						longitude: Number(item.lnt),
						joinCluster: true, // 产生聚合簇,需添加该属性
						zIndex: 99999,
						anchor: {
							x: .5,
							y: 1
						}
					}
					const newMarker = Object.assign({},markerObj)
			    	markers.push(newMarker)
					
			    })
				this._mapContext.addMarkers({
					markers,
					clear: this.ishandel?true:false, // 是否先清空地图上所有marker
				})
		},

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐