uni-app 小程序获取实时定位和车辆签到(wx.getLocation方法)

一、需求描述

        实现一个车辆定位签到功能,获取当前车辆的实时定位,当车辆到达签到点1公里范围内时,可以进行签到,当大于1公里时,禁止签到。同时用户还可以手动刷新定位。

二、wx.getLocation

        在之前的博客中,我写了一篇使用wx.onLocationChange进行定位签到的方法,见文章链接 uni-app 小程序获取实时定位和车辆签到(wx.onLocationChange方法),后面微信官方在2022年7月14日发布了一篇关于 “地理位置接口新增与相关流程调整” 的公告,见链接 地理位置接口新增与相关流程调整 | 微信开放社区公告说自 2022 年 7 月 14 日起,开发者在使用下表地理位置相关接口时,需要提前在 app.json 中进行配置:

        对于普通开发者,2022 年 7 月 14 日后发布的小程序,这8个API都需要在小程序管理后台完成权限申请,申请通过才能够在项目中使用,而我当时使用的wx.onLocationChange申请了多次一直被后台驳回,大概意思就是我这种定位签到应用场景,wx.onLocationChange支持的应用场景只支持下图所示的类目,而我的项目不符合wx.onLocationChange的应用场景,不需要实时监听用户的地理位置变化,所以没办法只能改为使用wx.getLocation方法。

 三、wx.getLocation使用流程

1、接口权限开通

        在 “小程序管理后台 -「开发」-「开发管理」-「接口设置」” 中完成wx.getLocation API权限申请;

 2、manifest.json(或app.json)配置

        uni-app需要在manifest.json配置"requiredPrivateInfos" : [ "getLocation" ]

3、核心代码

<template>
	<view class="container">
		<view class="map-box">
			<map id="myMap" :scale="14" :latitude="myLat" :longitude="myLon" :markers="markers" :circles="circles"></map>
			<view class="local-icon" @click="authorization"></view>
		</view>
		<view class="btn-box">
			<view class="cancel" v-if="info.workStatus == 1" @click="handleCancelTask">取消任务</view>
			<view class="submit" @click="handleSubmitSign" v-if="isAuth">确认签到</view>
			<view class="submit2" v-else>确认签到</view>
		</view>
	</view>
</template>

<script>
	import { host } from '../../config/config.js'
	export default {
		name: 'sign',
		data() {
			return {
				centerLon: 0,	// 中心经度
				centerLat: 0, 	// 中心纬度
				circles: [],	// 中心签到圈
				radius: 0,  	// 签到半径
				myLon: 0,    	// 当前定位经度
				myLat:0,	  	// 当前定位纬度
				markers: [],	// 当前定位标记点
				distance: 99999,// 车辆到签到中心点距离
				isAuth: false // 是否授权定位
			}
		},
		methods: {
			// 获取中心点坐标, 获取签到圈
			getCoordinate() {
				uni.request({
					url: host + '/api/v1/mini/driver/getCoordinate',
					method: 'GET',
					header:{
						'Content-Type' : 'application/json',
						token : uni.getStorageSync("TOKEN")
					},
					data: {},
					success: res => {
						if(res.data.code === "0") {
							console.log('中心的坐标', JSON.parse(JSON.stringify(res.data.data)))
							this.centerLon = res.data.data.longitude;
							this.centerLat = res.data.data.latitude;
							this.radius = res.data.data.radius;
							this.circles = [{
								longitude: this.centerLon,
								latitude: this.centerLat,
								fillColor: "#FF2B431A",
								color: "#FF0000",
								radius: this.radius,
								strokeWidth: 1
							}]
						} else {
							uni.showToast({
								title: res.data.msg,
								icon: 'none',
								duration: 2000
							});
						}
					},
					fail: () => {},
					complete: () => {}
				});
			},
 			// 获取用户是否授权定位
			authorization() {
				wx.authorize({
					scope: 'scope.userLocation',
					success: (res) => {
						console.log('获取授权成功');
						this.isAuth = true;
						uni.showLoading({
							title: '定位中...'
						});
						wx.getLocation({
							success: (res) => {
								console.log("获取当前初始位置成功", res);
								uni.hideLoading();
								this.drawLocaltionPoint(res);
							},
							fail: (err) => {
								console.log('获取当前初始位置失败', err);
								uni.hideLoading();
							}
						})
					},
					fail: (err) => {
						console.log('获取授权失败', err);
						this.handleOpenSetting();
					}
				})
			},
			// 用户授权定位
			handleOpenSetting() {
				uni.showModal({
					title: '温馨提示',
					content: '获取权限失败,需要获取您的地理位置才能为您提供更好的服务!是否授权获取地理位置?',
					success: (res) => {
						if (res.confirm) {
							wx.openSetting({
							    success: (res) => {
							        if (res.authSetting["scope.userLocation"]) {   // 用户同意授权
										console.log("用户同意授权");
										this.authorization();
							        }
							    }
							})
						}
					}
				});
			},
			// 绘制定位点
			drawLocaltionPoint(res) {
				console.log('绘制定位点:', res.longitude, res.latitude);
				this.myLon = res.longitude;
				this.myLat = res.latitude;
				this.markers = [{
					id: 1,
					longitude: this.myLon,
					latitude: this.myLat,
					iconPath: "../../static/img/record/point.png",
					width: 25,
					height: 25
				}]
			},
			// 确认签到,点击按钮时重新获取用户地理位置
			handleSubmitSign() {
				uni.showLoading({
					title: '定位中...'
				});
				wx.getLocation({
					success: (res) => {
						console.log("获取当前位置成功", res);
						uni.hideLoading();
						this.drawLocaltionPoint(res);
						this.handleSign();
					},
					fail: (err) => {
						console.log('获取当前位置失败', err);
						uni.hideLoading();
						this.handleSign();
					}
				})
			},
			// 签到
			handleSign() {
				this.distance = this.getDistance();
				console.log('签到距离:', this.distance, ' 签到半径:', this.radius);
				// 签到时进行判断,小于签到半径就签到成功,否则提示签到失败
				if(this.distance <= this.radius) {	
					// todo 签到成功,调用签到接口
				} else {
					uni.showToast({
						title: '签到失败,当前未在签到范围内,请稍后重试',
						icon: 'none',
						duration: 2500
					});
				}
			},
			// 获取当前位置距离签到点的距离
			getDistance() {
				let red1 = this.myLat * Math.PI / 180.0;
				let red2 = this.centerLat * Math.PI / 180.0;
				let a = red1 - red2;
				let b = this.myLon * Math.PI / 180.0 - this.centerLon * Math.PI / 180.0;
				let R = 6378137;
				let distance = R * 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(red1) * Math.cos(red2) * Math.pow(Math.sin(b / 2), 2)));
				return distance.toFixed(2) * 1;
			}
		},
		onLoad(option) {
			this.getCoordinate();
			this.authorization();
		}
	}
</script>

<style lang="less" scoped>
	.submit {
		color: #FFF;
		background: #FF2A41;
	}
	.submit2 {
		color: #FFF;
		background: #FF95A0;
	}
</style>

四、说明

        wx.getLocation是有调用频率限制的:

        1. 在开发版或体验版中,30秒内调用getLocation,仅第一次有效,剩余返回fail。

        2. 正式版中,为保证小程序正常运行同时不过度消耗用户电量,一定时间内(根据设备情况判断)调用getLocation,仅第一次会返回实时定位信息,剩余返回与第一次定位相同的信息。

        不管是体验版还是正式版,我都进行了兼容处理,使页面提示更加的友好,符合用户的操作习惯,在体验版中,如果30秒内再次点击确认签到,wx.getLocation会返回fail,执行到上面代码的第142行里面去,然后调用handleSign,签到距离大于半径,进行提示“签到失败,当前未在签到范围内,请稍后重试”;如果是正式版,如果30秒内再次点击确认签到,wx.getLocation会返回上一次的执行结果,执行到上面代码的第136行里面去,然后调用handleSign,签到距离大于半径,进行提示“签到失败,当前未在签到范围内,请稍后重试”所以,不管是正式版还是体验版,当用户频繁调用wx.getLocation,都会提示“签到失败,当前未在签到范围内,请稍后重试”,让用户以为是自己没有到达签到点的问题,当频繁调用频率一过,就会获得新的地理坐标,从而让用户体验更加的友好。

  • 5
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 18
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值