最近需要在小程序中做一个点位图,用于展示不同点位,且根据地图不同的缩放级别,实现多点位的聚合和分裂效果,使用uniapp提供的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
})
},