微信小程序如何使用地球半径计算两组经纬度点之间的距离(自身位置与接口返回位置)【上】

目录

1.配置位置权限

2.获取当前自身经纬度

[3. 请求接口拿到返回经纬](#3. 请求接口拿到返回经纬)

[4. 循环取每一项的经纬](#4. 循环取每一项的经纬)

5.如何判断是否打开了定位权限

6.进行距离计算操作

7.运行效果

8.完整代码

首先在使用小程序时,请求的接口一定要去配置合法域名,才能够进行接下来的操作。

1.配置位置权限

在app.json中添加如下代码:

 "permission": {
    "scope.userLocation": {
      "desc": "你的位置信息将用于小程序位置接口的效果展示"
    },
  }

2.获取当前自身经纬度

我们通过wx.getLocation这个api进行获取:

 wx.getLocation({
      type: 'gcj02',
      success(res) {
        that.setData({
          currentLatitude: res.latitude,
          currentLongitude: res.longitude
        });
})

在这里我们使用了变量来存放当前经纬度,并且使用that.setData({})方法来赋值,因为this的指向可能不明确,配置如下:

 data: {
      currentLatitude:'',
      currentLongitude:'',
}

  onLoad(options) {
    let that = this;
}

除了gcj02,还有以下几种地理位置坐标系类型可以选择:

  • wgs84:表示使用WGS84坐标系,也是全球卫星定位系统(GPS)所采用的坐标系。
  • bd09:表示使用百度坐标系,在国内常用的一种坐标系,适用于百度地图。
  • bd09ll:表示使用百度经纬度坐标系,与bd09相似,但在经度上更接近真实的经度值。

3. 请求接口拿到返回经纬

wx.request({
          url: '自己所使用的接口',
          method: 'POST',
          data: {},
          success: function(res) {
            console.log(res);
            that.setData({
              list: res.data.data.list
            });
}
})

上述代码呢list是我在data中的一个变量,用来存放我包含经纬度数据的数组,声明方式为list:[]

4. 循环取每一项的经纬

list数据格式如下:

 for (let i = 0; i < that.data.list.length; i++) {
              let item = that.data.list[i];
              let lat = parseFloat(item.latitude);
              let lon = parseFloat(item.longitude);
            }
            that.setData({
              list: that.data.list
            });

item.latitudeitem.longitude转换为浮点数(parseFloat())的目的是将字符串转换为数值型数据。这是因为经纬度通常以字符串的形式存储,在进行距离计算等数值操作时,需要将其转换为数值类型进行计算。通过使用parseFloat()函数,可以将字符串解析成浮点数,以便后续的数值计算。

5.如何判断是否打开了定位权限

在每一次打开此页面的时候都进行一次权限排查,如果没有打开定位权限,则会调起设置打开权限

checkLocationPermission() {
    let that = this;
    wx.getSetting({
      success(res) {
        if (!res.authSetting['scope.userLocation']) {
          wx.showModal({
            title: '提示',
            content: '您还没有启用定位权限,是否前往设置开启?',
            success(res) {
              if (res.confirm) {
                // User confirmed opening settings
                wx.openSetting({
                  success(res) {
                    if (res.authSetting['scope.userLocation']) {
                      // User granted location permission in settings
                      that.onLoad(); // Reload the page to fetch data with location permission
                    } else {
                      // User did not grant location permission in settings
                      wx.showToast({
                        title: '您还未开启定位权限',
                        icon: 'none'
                      });
                    }
                  }
                });
              } else if (res.cancel) {
                console.log(res.cancel);
                // User canceled opening settings
                wx.showToast({
                  title: '您还未开启定位权限',
                  icon: 'none'
                });
              }
            }
          });
        }
      }
    });
  },

因为此代码是排查权限信息,所以单独写了个函数,你可以选择在onshow或者onload中调用

  onShow() {
    this.checkLocationPermission();
  },

6.进行距离计算操作

  getDistance: function(lat1, lon1, lat2, lon2) {
    var R = 6371;
    var dLat = (lat2 - lat1) * Math.PI / 180;
    var dLon = (lon2 - lon1) * Math.PI / 180;
    var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
            Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
            Math.sin(dLon / 2) * Math.sin(dLon / 2);
    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    var distance = R * c; 
    return distance.toFixed(2);
  },

详解代码:

  • var R = 6371;:定义地球的半径,单位为公里。这是用于计算两点间距离的基准。

  • var dLat = (lat2 - lat1) * Math.PI / 180;:计算两点纬度差值,并将其转换为弧度值。

  • var dLon = (lon2 - lon1) * Math.PI / 180;:计算两点经度差值,并将其转换为弧度值。

  • var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) * Math.sin(dLon / 2) * Math.sin(dLon / 2);:根据Haversine公式,计算两点间的距离。

    • Math.sin(dLat / 2) * Math.sin(dLat / 2):计算纬度差值的一半的正弦平方。
    • Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180):计算两点纬度的余弦乘积。
    • Math.sin(dLon / 2) * Math.sin(dLon / 2):计算经度差值的一半的正弦平方。
    • 将上述三个部分相加得到a的值,表示两点间的角距离。
  • var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));:根据球面三角学公式,计算角距离对应的弧长。

    • Math.sqrt(a):计算a的平方根。
    • Math.sqrt(1 - a):计算1 - a的平方根。
    • Math.atan2():计算给定坐标的反正切值。
  • var distance = R * c;:将弧长乘以地球半径,得到两点间的直线距离,单位为公里。

  • return distance.toFixed(2);:返回计算得到的距离,并将其保留两位小数。

最后需要调用函数到接口操作中(上述的for循环):

for (let i = 0; i < that.data.list.length; i++) {
              let item = that.data.list[i];
              let lat = parseFloat(item.latitude);
              let lon = parseFloat(item.longitude);
              let distance = that.getDistance(that.data.currentLatitude, that.data.currentLongitude, lat, lon);
              item.distance = distance;
            }
            that.setData({
              list: that.data.list
            });

7.运行效果

8.完整代码

Page({

  /**
   * 页面的初始数据
   */
  data: {
      list:[],
      currentLatitude:'',
      currentLongitude:'',
     
  },

  /**
   * 生命周期函数--监听页面加载
   */
  handleImageError(e){
  onLoad(options) {
    let that = this;
    wx.getLocation({
      type: 'gcj02',
      success(res) {
        that.setData({
          currentLatitude: res.latitude,
          currentLongitude: res.longitude
        });
        
        wx.request({
          url: '',
          method: 'POST',
          data: {},
          success: function(res) {
            console.log(res);
            that.setData({
              list: res.data.data.list
            });
            
            for (let i = 0; i < that.data.list.length; i++) {
              let item = that.data.list[i];
              let lat = parseFloat(item.latitude);
              let lon = parseFloat(item.longitude);
              let distance = that.getDistance(that.data.currentLatitude, that.data.currentLongitude, lat, lon);
              item.distance = distance;
            }
            that.setData({
              list: that.data.list
            });
          },
        });
      },
      fail(res) {
        wx.showModal({
          title: '提示',
          content: '您还没有启用定位权限,是否前往设置开启?',
          success(res) {
            if (res.confirm) {
              wx.openSetting({
                success(res) {
                  if (res.authSetting['scope.userLocation']) {
                    that.onLoad(options); 
                  } else {
                    wx.showToast({
                      title: '您还未开启定位权限',
                      icon: 'none'
                    });
                  }
                }
              });
            } else if (res.cancel) {
              console.log(res.cancel);
              wx.showToast({
                title: '您还未开启定位权限',
                icon: 'none'
              });
            }
          }
        });
      }
    });
  },
  
  onShow() {
    this.checkLocationPermission();
  },
  
  checkLocationPermission() {
    let that = this;
    wx.getSetting({
      success(res) {
        if (!res.authSetting['scope.userLocation']) {
          wx.showModal({
            title: '提示',
            content: '您还没有启用定位权限,是否前往设置开启?',
            success(res) {
              if (res.confirm) {
                wx.openSetting({
                  success(res) {
                    if (res.authSetting['scope.userLocation']) {
                      that.onLoad(); 
                    } else {
                      wx.showToast({
                        title: '您还未开启定位权限',
                        icon: 'none'
                      });
                    }
                  }
                });
              } else if (res.cancel) {
                console.log(res.cancel);
                wx.showToast({
                  title: '您还未开启定位权限',
                  icon: 'none'
                });
              }
            }
          });
        }
      }
    });
  },
  
  getDistance: function(lat1, lon1, lat2, lon2) {
    var R = 6371; 
    var dLat = (lat2 - lat1) * Math.PI / 180;
    var dLon = (lon2 - lon1) * Math.PI / 180;
    var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
            Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
            Math.sin(dLon / 2) * Math.sin(dLon / 2);
    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    var distance = R * c;
    return distance.toFixed(2);
  },
  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  

  onReady() {

  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow() {

  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide() {

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload() {

  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh() {

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom() {

  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage() {

  }
})

微信小程序如何利用接口返回经纬计算实际位置并且进行导航功能【下】
https://blog.csdn.net/m0_71966801/article/details/134084525?spm=1001.2014.3001.5502

相关推荐
鸠摩智首席音效师1 分钟前
如何在 Apache 中创建单个文件的别名 ?
apache
滚雪球~11 分钟前
npm error code ETIMEDOUT
前端·npm·node.js
沙漏无语13 分钟前
npm : 无法加载文件 D:\Nodejs\node_global\npm.ps1,因为在此系统上禁止运行脚本
前端·npm·node.js
supermapsupport14 分钟前
iClient3D for Cesium在Vue中快速实现场景卷帘
前端·vue.js·3d·cesium·supermap
brrdg_sefg16 分钟前
WEB 漏洞 - 文件包含漏洞深度解析
前端·网络·安全
胡西风_foxww22 分钟前
【es6复习笔记】rest参数(7)
前端·笔记·es6·参数·rest
m0_7482548823 分钟前
vue+elementui实现下拉表格多选+搜索+分页+回显+全选2.0
前端·vue.js·elementui
YUJIAN。41 分钟前
使用uniapp开发微信小程序-框架搭建
微信小程序·小程序·uni-app
星就前端叭1 小时前
【开源】一款基于Vue3 + WebRTC + Node + SRS + FFmpeg搭建的直播间项目
前端·后端·开源·webrtc
m0_748234521 小时前
前端Vue3字体优化三部曲(webFont、font-spider、spa-font-spider-webpack-plugin)
前端·webpack·node.js