• 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、核心代码

    1. <template>
    2. <view class="container">
    3. <view class="map-box">
    4. <map id="myMap" :scale="14" :latitude="myLat" :longitude="myLon" :markers="markers" :circles="circles">map>
    5. <view class="local-icon" @click="authorization">view>
    6. view>
    7. <view class="btn-box">
    8. <view class="cancel" v-if="info.workStatus == 1" @click="handleCancelTask">取消任务view>
    9. <view class="submit" @click="handleSubmitSign" v-if="isAuth">确认签到view>
    10. <view class="submit2" v-else>确认签到view>
    11. view>
    12. view>
    13. template>
    14. <script>
    15. import { host } from '../../config/config.js'
    16. export default {
    17. name: 'sign',
    18. data() {
    19. return {
    20. centerLon: 0, // 中心经度
    21. centerLat: 0, // 中心纬度
    22. circles: [], // 中心签到圈
    23. radius: 0, // 签到半径
    24. myLon: 0, // 当前定位经度
    25. myLat:0, // 当前定位纬度
    26. markers: [], // 当前定位标记点
    27. distance: 99999,// 车辆到签到中心点距离
    28. isAuth: false // 是否授权定位
    29. }
    30. },
    31. methods: {
    32. // 获取中心点坐标, 获取签到圈
    33. getCoordinate() {
    34. uni.request({
    35. url: host + '/api/v1/mini/driver/getCoordinate',
    36. method: 'GET',
    37. header:{
    38. 'Content-Type' : 'application/json',
    39. token : uni.getStorageSync("TOKEN")
    40. },
    41. data: {},
    42. success: res => {
    43. if(res.data.code === "0") {
    44. console.log('中心的坐标', JSON.parse(JSON.stringify(res.data.data)))
    45. this.centerLon = res.data.data.longitude;
    46. this.centerLat = res.data.data.latitude;
    47. this.radius = res.data.data.radius;
    48. this.circles = [{
    49. longitude: this.centerLon,
    50. latitude: this.centerLat,
    51. fillColor: "#FF2B431A",
    52. color: "#FF0000",
    53. radius: this.radius,
    54. strokeWidth: 1
    55. }]
    56. } else {
    57. uni.showToast({
    58. title: res.data.msg,
    59. icon: 'none',
    60. duration: 2000
    61. });
    62. }
    63. },
    64. fail: () => {},
    65. complete: () => {}
    66. });
    67. },
    68. // 获取用户是否授权定位
    69. authorization() {
    70. wx.authorize({
    71. scope: 'scope.userLocation',
    72. success: (res) => {
    73. console.log('获取授权成功');
    74. this.isAuth = true;
    75. uni.showLoading({
    76. title: '定位中...'
    77. });
    78. wx.getLocation({
    79. success: (res) => {
    80. console.log("获取当前初始位置成功", res);
    81. uni.hideLoading();
    82. this.drawLocaltionPoint(res);
    83. },
    84. fail: (err) => {
    85. console.log('获取当前初始位置失败', err);
    86. uni.hideLoading();
    87. }
    88. })
    89. },
    90. fail: (err) => {
    91. console.log('获取授权失败', err);
    92. this.handleOpenSetting();
    93. }
    94. })
    95. },
    96. // 用户授权定位
    97. handleOpenSetting() {
    98. uni.showModal({
    99. title: '温馨提示',
    100. content: '获取权限失败,需要获取您的地理位置才能为您提供更好的服务!是否授权获取地理位置?',
    101. success: (res) => {
    102. if (res.confirm) {
    103. wx.openSetting({
    104. success: (res) => {
    105. if (res.authSetting["scope.userLocation"]) { // 用户同意授权
    106. console.log("用户同意授权");
    107. this.authorization();
    108. }
    109. }
    110. })
    111. }
    112. }
    113. });
    114. },
    115. // 绘制定位点
    116. drawLocaltionPoint(res) {
    117. console.log('绘制定位点:', res.longitude, res.latitude);
    118. this.myLon = res.longitude;
    119. this.myLat = res.latitude;
    120. this.markers = [{
    121. id: 1,
    122. longitude: this.myLon,
    123. latitude: this.myLat,
    124. iconPath: "../../static/img/record/point.png",
    125. width: 25,
    126. height: 25
    127. }]
    128. },
    129. // 确认签到,点击按钮时重新获取用户地理位置
    130. handleSubmitSign() {
    131. uni.showLoading({
    132. title: '定位中...'
    133. });
    134. wx.getLocation({
    135. success: (res) => {
    136. console.log("获取当前位置成功", res);
    137. uni.hideLoading();
    138. this.drawLocaltionPoint(res);
    139. this.handleSign();
    140. },
    141. fail: (err) => {
    142. console.log('获取当前位置失败', err);
    143. uni.hideLoading();
    144. this.handleSign();
    145. }
    146. })
    147. },
    148. // 签到
    149. handleSign() {
    150. this.distance = this.getDistance();
    151. console.log('签到距离:', this.distance, ' 签到半径:', this.radius);
    152. // 签到时进行判断,小于签到半径就签到成功,否则提示签到失败
    153. if(this.distance <= this.radius) {
    154. // todo 签到成功,调用签到接口
    155. } else {
    156. uni.showToast({
    157. title: '签到失败,当前未在签到范围内,请稍后重试',
    158. icon: 'none',
    159. duration: 2500
    160. });
    161. }
    162. },
    163. // 获取当前位置距离签到点的距离
    164. getDistance() {
    165. let red1 = this.myLat * Math.PI / 180.0;
    166. let red2 = this.centerLat * Math.PI / 180.0;
    167. let a = red1 - red2;
    168. let b = this.myLon * Math.PI / 180.0 - this.centerLon * Math.PI / 180.0;
    169. let R = 6378137;
    170. 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)));
    171. return distance.toFixed(2) * 1;
    172. }
    173. },
    174. onLoad(option) {
    175. this.getCoordinate();
    176. this.authorization();
    177. }
    178. }
    179. script>
    180. <style lang="less" scoped>
    181. .submit {
    182. color: #FFF;
    183. background: #FF2A41;
    184. }
    185. .submit2 {
    186. color: #FFF;
    187. background: #FF95A0;
    188. }
    189. style>

    四、说明

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

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

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

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

  • 相关阅读:
    百度地图在vue中的使用
    NaiveUI中看起来没啥用的组件(文字渐变)实现原来这么简单
    “2024上海智博会”为我国智能科技产业发展注入新的动力
    科研论文作图小技巧
    论文阅读:YOLOV: Making Still Image Object Detectors Great at Video Object Detection
    react中遇到的分页问题
    Docker 入门到实战 之 安装RocketMQ
    2004-2019年分省农产品进出口额
    栈和队列
    Hue在大数据生态圈的集成
  • 原文地址:https://blog.csdn.net/qq_40007317/article/details/127428880