The uniapp WeChat applet calculates the distance from the user to nearby institutions/stores based on the user's current location

1. First of all, it is necessary to figure out which category the longitude and latitude transmitted from the backend belong to. There are three categories in total, namely: WGS84, GCJ02, BD09
WGS84: It is a geodetic coordinate system, and it is also the GPS global satellite positioning widely used at present. The coordinate system used by the system.
GCJ02: Also known as the Mars coordinate system, it is a geographic coordinate system formulated by the National Bureau of Surveying and Mapping of China, and a coordinate system obtained by encrypting WGS84.
BD09: Baidu coordinate system, encrypted again on the basis of GCJ02 coordinate system. Among them, bd09ll indicates Baidu longitude and latitude coordinates, and bd09mc indicates Baidu Mercator metric coordinates.

2. Baidu, Gaode, and Google use the corresponding types of
Baidu map——BD09
Gaode map——GCJ02
Google map——GCJ02

3. Then it is the latitude and longitude location obtained by the user. uniapp provides the method uni.getLocation(), use The method is as follows, the default is wgs84 type

uni.getLocation({
    
    
	type: 'wgs84',
	success: function (res) {
    
    
		console.log('当前位置的经度:' + res.longitude);
		console.log('当前位置的纬度:' + res.latitude);
	}
});

4. Then you need to know whether the latitude and longitude returned by the backend is Gaode, Baidu, or Google, and convert the obtained latitude and longitude of the user. The conversion method is as follows:

/**
 * 
 * 提供了百度坐标(BD09)、国测局坐标(火星坐标,GCJ02)、和WGS84坐标系之间的转换
 */
// UMD魔法代码
// if the module has no dependencies, the above pattern can be simplified to
/* eslint-disable */
 
let coordtransform = function () {
    
    
  // 定义一些常量
  let x_PI = 3.14159265358979324 * 3000.0 / 180.0;
  let PI = 3.1415926535897932384626;
  let a = 6378245.0;
  let ee = 0.00669342162296594323;
  /**
   * 百度坐标系 (BD-09) 与 火星坐标系 (GCJ-02)的转换
   * 即 百度 转 谷歌、高德
   * @param bd_lon
   * @param bd_lat
   * @returns {*[]}
   */
  let bd09togcj02 = function bd09togcj02(bd_lon, bd_lat) {
    
    
    bd_lon = +bd_lon;
    bd_lat = +bd_lat;
    let x = bd_lon - 0.0065;
    let y = bd_lat - 0.006;
    let z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_PI);
    let theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_PI);
    let gg_lng = z * Math.cos(theta);
    let gg_lat = z * Math.sin(theta);
    return [gg_lng, gg_lat]
  };
 
  /**
   * 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换
   * 即谷歌、高德 转 百度
   * @param lng
   * @param lat
   * @returns {*[]}
   */
  let gcj02tobd09 = function gcj02tobd09(lng, lat) {
    
    
    lat = +lat;
    lng = +lng;
    let z = Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * x_PI);
    let theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * x_PI);
    let bd_lng = z * Math.cos(theta) + 0.0065;
    let bd_lat = z * Math.sin(theta) + 0.006;
    return [bd_lng, bd_lat]
  };
 
  /**
   * WGS84转GCj02
   * @param lng
   * @param lat
   * @returns {*[]}
   */
  let wgs84togcj02 = function wgs84togcj02(lng, lat) {
    
    
    lat = +lat;
    lng = +lng;
    if (out_of_china(lng, lat)) {
    
    
      return [lng, lat]
    } else {
    
    
      let dlat = transformlat(lng - 105.0, lat - 35.0);
      let dlng = transformlng(lng - 105.0, lat - 35.0);
      let radlat = lat / 180.0 * PI;
      let magic = Math.sin(radlat);
      magic = 1 - ee * magic * magic;
      let sqrtmagic = Math.sqrt(magic);
      dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * PI);
      dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * PI);
      let mglat = lat + dlat;
      let mglng = lng + dlng;
      return [mglng, mglat]
    }
  };
 
  /**
   * GCJ02 转换为 WGS84
   * @param lng
   * @param lat
   * @returns {*[]}
   */
  let gcj02towgs84 = function gcj02towgs84(lng, lat) {
    
    
    lat = +lat;
    lng = +lng;
    if (out_of_china(lng, lat)) {
    
    
      return [lng, lat]
    } else {
    
    
      let dlat = transformlat(lng - 105.0, lat - 35.0);
      let dlng = transformlng(lng - 105.0, lat - 35.0);
      let radlat = lat / 180.0 * PI;
      let magic = Math.sin(radlat);
      magic = 1 - ee * magic * magic;
      let sqrtmagic = Math.sqrt(magic);
      dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * PI);
      dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * PI);
      let mglat = lat + dlat;
      let mglng = lng + dlng;
      return [lng * 2 - mglng, lat * 2 - mglat]
    }
  };
 
  let transformlat = function transformlat(lng, lat) {
    
    
    lat = +lat;
    lng = +lng;
    let ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng));
    ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
    ret += (20.0 * Math.sin(lat * PI) + 40.0 * Math.sin(lat / 3.0 * PI)) * 2.0 / 3.0;
    ret += (160.0 * Math.sin(lat / 12.0 * PI) + 320 * Math.sin(lat * PI / 30.0)) * 2.0 / 3.0;
    return ret
  };
 
  let transformlng = function transformlng(lng, lat) {
    
    
    lat = +lat;
    lng = +lng;
    let ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng));
    ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
    ret += (20.0 * Math.sin(lng * PI) + 40.0 * Math.sin(lng / 3.0 * PI)) * 2.0 / 3.0;
    ret += (150.0 * Math.sin(lng / 12.0 * PI) + 300.0 * Math.sin(lng / 30.0 * PI)) * 2.0 / 3.0;
    return ret
  };
 
  /**
   * 判断是否在国内,不在国内则不做偏移
   * @param lng
   * @param lat
   * @returns {boolean}
   */
  let out_of_china = function out_of_china(lng, lat) {
    
    
    lat = +lat;
    lng = +lng;
    // 纬度3.86~53.55,经度73.66~135.05
    return !(lng > 73.66 && lng < 135.05 && lat > 3.86 && lat < 53.55);
  };
 
  return {
    
    
    bd09togcj02: bd09togcj02,
    gcj02tobd09: gcj02tobd09,
    wgs84togcj02: wgs84togcj02,
    gcj02towgs84: gcj02towgs84
  }
}();
 
export default coordtransform

4. Calculation formulas. At present, the calculation of the distance between two points on the market is basically based on the law of cosine spheres. This law uses trigonometric functions to measure the curvature of the earth to accurately measure the distance on the earth.

// 经纬度转换成三角函数中度分表形式。
rad(d) {
    
    
    return d * Math.PI / 180.0;
},
// 根据经纬度计算距离,参数分别为第一点的纬度,经度;第二点的纬度,经度
getDistance(lat1, lng1, lat2, lng2) {
    
    
    let radLat1 = this.rad(lat1);
    let radLat2 = this.rad(lat2);
    let a = radLat1 - radLat2;
    let b = this.rad(lng1) - this.rad(lng2);
    let s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) +
        Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
    s = s * 6378.137; // EARTH_RADIUS;
    s = Math.round(s * 10000) / 10000; //输出为公里
    let distance = s;
    let distance_str = "";
    parseInt(distance) >= 1 ? distance_str = distance.toFixed(1) + "km" : distance_str = distance * 1000 + "m"
    return [s,distance_str];
},

5. My example in the project:

      data(){
    
    
              // 获取距离所用参数
        latitude: 0, // 纬度
        longitude: 0, // 经度
	  }

	// 获取定位
      getAddressInfo(){
    
    
        let that = this
        // 获取用户是否开启 授权获取当前的地理位置、速度的权限。
        uni.getSetting({
    
    
          success (res) {
    
    
            console.log(res)
            // 如果没有授权
            if (!res.authSetting['scope.userLocation']) {
    
    
              // 则拉起授权窗口
              uni.authorize({
    
    
                scope: 'scope.userLocation',
                success () {
    
    
                //点击允许后--就一直会进入成功授权的回调 就可以使用获取的方法了
                  uni.getLocation({
    
    
                    type: 'wgs84',
                    success: function (res) {
    
    
                        let a = coordtransform.wgs84togcj02(res.longitude, res.latitude)
                        that.latitude = a[1]
                        that.longitude = a[0]
                    }, fail (error) {
    
    
                      that.$util.showMessage('当前位置获取失败,将不显示相关机构到此的距离', 1500)
                    }
                  })
                },
                fail (error) {
    
    
                  uni.showModal({
    
    
                      content: '当前位置获取失败,将不显示相关机构到此的距离',
                      cancelText: '不授权',
                      cancelColor: '#999999',
                      confirmText: '授权',
                      confirmColor: '#f94218',
                      success (res) {
    
    
                        console.log(res)
                        if (res.confirm) {
    
    
                          // 选择弹框内授权
                          uni.openSetting({
    
    
                            success (res) {
    
    
                              uni.getLocation({
    
    
                                type: 'wgs84',
                                success: function (res) {
    
    
                                  let a = coordtransform.wgs84togcj02(res.longitude, res.latitude)
                                  that.latitude = a[1]
                                  that.longitude = a[0]
                                }, fail (error) {
    
    
                                  that.$util.showMessage('获取地址失败,请检查手机是否打开定位功能', 1500)
                                }
                              })
                            }
                          })
                        }
                      }
                  })
                  return
                }
              })
            } else {
    
    
              // 有权限则直接获取
              uni.getLocation({
    
    
                type: 'wgs84',
                success: function (res) {
    
    
                  let a = coordtransform.wgs84togcj02(res.longitude, res.latitude)
                  that.latitude = a[1]
                  that.longitude = a[0]
                }, fail (error) {
    
    
                  that.$util.showMessage('获取地址失败,请检查手机是否打开定位功能', 1500)
                }
              })
            }
          }
        })
      },


// 通过调用接口,拿到数据进行计算(我这里计算后还进行了排序,所以多了一步)
if(that.latitude != 0 && that.longitude != 0){
    
    
         res.storeList.forEach(item => {
    
    
            item.distance = that.getDistance(that.latitude,that.longitude,item.storeLat,item.storeLng)[1]
            item.distanceFloat = that.getDistance(that.latitude,that.longitude,item.storeLat,item.storeLng)[0]
        })
        let temp = 0
        for (let i = 0; i <= res.storeList.length - 1; i++) {
    
    
           for (let j = 0; j < res.storeList.length - i - 1; j++) {
    
    
             if (parseFloat(res.storeList[j].distanceFloat) > parseFloat(res.storeList[j + 1].distanceFloat)) {
    
    
               temp = res.storeList[j]
               res.storeList[j] = res.storeList[j + 1]
               res.storeList[j + 1] = temp
            }
         }
       }
}

Guess you like

Origin blog.csdn.net/weixin_44949068/article/details/129167098