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

目录

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

相关推荐
dr李四维10 分钟前
iOS构建版本以及Hbuilder打iOS的ipa包全流程
前端·笔记·ios·产品运营·产品经理·xcode
雯0609~31 分钟前
网页F12:缓存的使用(设值、取值、删除)
前端·缓存
℘团子এ34 分钟前
vue3中如何上传文件到腾讯云的桶(cosbrowser)
前端·javascript·腾讯云
学习前端的小z40 分钟前
【前端】深入理解 JavaScript 逻辑运算符的优先级与短路求值机制
开发语言·前端·javascript
彭世瑜1 小时前
ts: TypeScript跳过检查/忽略类型检查
前端·javascript·typescript
FØund4041 小时前
antd form.setFieldsValue问题总结
前端·react.js·typescript·html
Backstroke fish1 小时前
Token刷新机制
前端·javascript·vue.js·typescript·vue
小五Five1 小时前
TypeScript项目中Axios的封装
开发语言·前端·javascript
小曲程序1 小时前
vue3 封装request请求
java·前端·typescript·vue
临枫5411 小时前
Nuxt3封装网络请求 useFetch & $fetch
前端·javascript·vue.js·typescript