这几天忙着开发微信小程序模块,此页用来记录开发遇到的一些问题,同时也帮助大家避坑。
这个问题很重要,如果需要进行map开发的话,需要注意,在uniapp中如果要使用自定义气泡Callout的话,要有Callout可能被地图覆盖的准备,因为地图的层级高于cover-view,而微信官方截至目前仍未给出解决的方案,uniapp官方建议是使用nvue开发或者使用SubNVue进行原生开发,当然这两种我都没有进行实验(SubNVue尝试了一下,满红红,赶紧回退).当markers第二次刷新的时候就会出现气泡被map覆盖的问题,可以尝试在刷新markers之前先将markers缓存刷新一下,这样就可以刷新到map了。
//刷新地图视图
//coversLength为markers容器的长度
refreshMap(coversLength) {
var _this5 = this;
var markersC = [];
for (let i = 0; i < coversLength; i++) {
markersC.push(_this5.covers[i]);
}
//刷新一下markers的缓存
uni.removeMarkers({
markerIds: [1],
});
//将covers中的数据刷新到marker中
this.mapContext.addMarkers({
markers: markersC,
clear: true
});
//地图定位到用户当前位置
this.mapContext.moveToLocation({
latitude: markersC[0].latitude,
longitude: markersC[0].longitude
});
//放大位置
_this5.zoomMapUp("add");
}
同时在使用地图定位时,如果没有申请微信小程序接口则无法调用uni.onLocationChange(实时位置更新),只能使用uni.getLocation(获取当前经纬度),而该接口在PC微信开发者工具调试时只能使用2.24.1版本进行调试,新版本可能造成调试时无法调用,但在真机调试还是可以正常使用,但是不能在指定时间内多次调用,否则会返回调用失败。
使用定位时,还需要先获取用户权限
//检查用户是否已经授权访问scope属性
isGetLocation(a = "scope.userLocation") {
var _this = this;
uni.getSetting({
success(res) {
console.log("isGetLocation", res)
//如果没有授权就去获得授权
//如果获得授权,用户自己选择是否更新位置(更新到用户当前位置)
if (!res.authSetting[a]) {
//去获取授权
_this.getAuthorizeInfo()
} else {
//当拥有授权时,询问用户是否手动更新位置
uni.showModal({
title: '提示',
content: '是否更新位置',
confirmText: "更新",
cancelText: "取消",
success: (res) => {
if (res.confirm) {
//直接更新到用户当前位置
//_this.getMlocationInfo();
_this.getLocation();
}
_this.isAuthorize = true;
}
});
}
}
});
}
不管成功与否,就没有二次授权的机会了,后面用户重新打开小程序也没用,除非清除本地缓存,这时候就需要用户手动打开授权。
// uniapp弹窗弹出获取授权(地理,个人微信信息等授权信息)弹窗
getAuthorizeInfo(a = "scope.userLocation") {
var _this = this;
//当用户使用该授权后,不管是否授权都不会进行二次询问
//也无法拉起授权窗口,需要进行二次授权
uni.authorize({
scope: 'scope.userLocation',
//允许授权,则获取用户当前位置
success() {
// 方式二,获取用户经纬度
_this.isAuthorize = true;
_this.getLocation();
},
//取消授权则询问二次授权
fail() {
uni.showModal({
title: "提示",
content: '请授权,否则无法更新附近人',
cancelText: "取消",
confirmText: "去授权",
//如果二次授权成功,直接自己调用授权接口转为成功
success: (res) => {
if (res.confirm) {
uni.openSetting({
success(settingdata) {
if (settingdata.authSetting[
'scope.userLocation'
]) {
uni.showModal({
title: '提示',
content: '授权成功',
showCancel: false
})
_this.isAuthorize = true;
_this.getLocation();
}
}
})
}
}
})
}
})
}
在使用地图时需要在地图上标记点位,通过获取的经纬度可以配置marker,在使用时需要注意,通过地图上下文容器进行markers的赋值时,需要创建新的对象,而不能直接用同一个对象赋值,否则markers可能会不刷新。
//装入用户id
_this4.covers[0].id = nowUserId;
//返回的附近人数组对象
var nearPeopleArr = Array.from(res);
//附近人id
var nearPeopleId;
//附近人名
var nearPeopleName;
//附近人职位
var nearPosition;
//附近人维度
var nearPeopleWei;
//附近人经度
var nearPeopleJin;
//头像图片链接
var nearPeopleImge;
//获取数组长度方便遍历
const arrayLengths = nearPeopleArr.length;
//将当前用户信息保留
const userCoverHand = this.covers[0];
//更新载体
let upCovers = [];
for (var p in nearPeopleArr) {
//附近人id
nearPeopleId = nearPeopleArr[p].id;
//附近人姓名
nearPeopleName = nearPeopleArr[p].fullName;
//附近人职位
nearPosition = nearPeopleArr[p].jobPosition;
//附近人纬度
nearPeopleWei = nearPeopleArr[p].latWei;
//附近人经度
nearPeopleJin = nearPeopleArr[p].lngJin;
//头像图片链接
nearPeopleImge = nearPeopleArr[p].personImage;
//更新附近人的markers参数
upCovers.push({
id: Number(nearPeopleId),
latitude: Number(nearPeopleWei),
longitude: Number(nearPeopleJin),
iconPath: 'https://hellouniapp.dcloud.net.cn/static/location.png',
userImage: nearPeopleImge,
fullName: nearPeopleName,
userPosition: nearPosition,
width: "40",
height: "40",
//参与聚合默认false就是不参与聚合
joinCluster: true,
//自定义气泡窗口
customCallout: {
//x,y气泡位置
anchorX: -75,
anchorY: 20,
content: nearPeopleName,
padding: 7,
borderRadius: 5,
textAlign: "center",
//设置markers的自定义气泡显示方式
display: "ALWAYS"
}
});
}
this.covers = upCovers;
//将当前用户插入markers
this.covers.splice(0, 0, userCoverHand);
_this4.refreshMap(arrayLengths);
});
//........................
var markersC = [];
for (let i = 0; i < coversLength; i++) {
markersC.push(_this5.covers[i]);
}
//刷新一下markers的缓存,随便移哪个都可以
uni.removeMarkers({
markerIds: [1],
});
//将covers中的数据刷新到marker中
this.mapContext.addMarkers({
markers: markersC,
clear: true
});
让covers指向一个新的对象,这样才能被markers检测是新的数据进行存储。
当点击一个markers或者用户要回到自己当前位置时,会将视角移动到当前点位,但是不会进行放大,如果用户缩的很小的时候甚至不会移动,正常情况下都需要定位到marker位置然后进行一个放大,但是在放大时也遇到了问题,缩放系数scale在函数中无法刷新到map中。
通过uniapp.getScale可以获得当前用户的缩放系数,根据情况传入参数控制地图的缩放,然后通过自增加减刷新到map中。(先移动到marker,再放大).
同时移动的api需要传入Number对象,建议在传入的时候直接就括一下,防止出现问题.
this.mapContext.moveToLocation({
//参数类型必须转化成Number,否则一直跳自己原点
latitude: Number(marker.latitude),
longitude: Number(marker.longitude),
});
另外uni.chooseLocation这个API是用来给用户手动选择位置的,但是现在调用这个api后,用户无法取消退出选择(未解决),如果有大佬知道怎样解决可以评论直接发出来,也帮大家一起看看解决一下,感激不尽.
//有问题,不能退出
uni.chooseLocation({
success: (res) => {
console.log('chooseLocation', res)
if (res.errMsg == "chooseLocation:ok") {
//this.address_info = res.name + res.address;
_this.latitude = res.latitude;
_this.longitude = res.longitude;
_this.covers[0].latitude = res.latitude;
_this.covers[0].longitude = res.longitude;
_this.getNearbyPeople();
}
}
});
另外最后一些就是在微信开发者工具上进行调试时,聚合簇是无法运行的,需要在真机上才能体现效果,并且在调试时,我还遇到了奇葩的微信版本问题导致调试器无法显示任何调试信息和数据(问题版本 8.0.37),在更新到8.0.40后就正常可以显示数据了。
另外记录一下,项目中的url配置文件存在index.js中
最后总结,前端用起来很便捷但是问题也很多,作为一个后端在使用时很便捷,但是在寻找问题和进行数据交互的时候就非常的痛苦,前端的框架更是一言难尽,使用了uniapp后我感觉这个框架还有很长的一段路需要行走,需要探索。