记一次根据经纬度计算距离的项目实践

记一次根据经纬度计算距离的项目实践

朱治龙
2021-06-30 / 0 评论 / 139 阅读 / 正在检测是否收录...
温馨提示:
本文最后更新于2023年10月20日,已超过446天没有更新,若内容或图片失效,请留言反馈。

kqytkdfn.png

近期公司接的公租房项目,在小程序模块中有用到离我最近的房源列表的功能,经过项目实践相关实现过程如下:

功能演示

PC后台配置小区位置:

小区位置配置入口
单击地图描点后打开如下图所示的描点对话框,描点选择后单击确定按钮返回经纬度信息:
地图描点

小程序中获取位置后调用接口显示距离:

小程序中效果

代码实现:

管理后台描点Vue组件核心代码

<template>
  <el-dialog width="95%" class="hkt-dlg-darkblue resource-modal" top="5vh" :title="title" :visible.sync="isShow" destroy-on-close :close-on-click-modal="false">
    <div class="map-container" ref="mapContainer"></div>
    <div slot="footer" class="dialog-footer dialog-footer-wrap text-center">
      <el-button @click="isShow = false">取 消</el-button>
      <el-button type="primary" :disabled="!latitude" @click="pickedHandler">{{'确 定'}}</el-button>
    </div>
  </el-dialog>
</template>
<script>
export default {
  name: 'PickerQMapPositionModal',
  props: {
    show: {
      type: Boolean,
      default: false
    },
    title: {
      type: String,
      default: '地图描点'
    },
    dialogProps: {
      type: Object,
      reuired: true
    }
  },
  data () {
    return {
      latitude: '',
      longitude: ''
    }
  },
  computed: {
    isShow: {
      get () {
        return this.show
      },
      set (val) {
        this.$emit('update:show', val)
      }
    }
  },
  mounted () {
    this.init()
  },
  methods: {
    init () {
      this.initMap()
    },
    async initMap () {
      // if (!window.TMap) {
      //   }
      await this.$hktUtils.loadJS('https://map.qq.com/api/gljs?v=1.exp&key=VQ6BZ-ZFSW6-H36SN-E7TZL-QZ6U6-O3F24')
      var center = new TMap.LatLng(28.239377,112.866161)
      //定义map变量,调用 TMap.Map() 构造函数创建地图
      var map = new TMap.Map(this.$refs.mapContainer, {
          center: center,//设置地图中心点坐标
          zoom: 15,   //设置地图缩放级别
          // pitch: 43.5,  //设置俯仰角
          // rotation: 45    //设置地图旋转角度
      });
      //初始化marker图层
      var markerLayer = new TMap.MultiMarker({
          id: 'marker-layer',
          map: map
      });
      map.on("click", (evt) => {
        if(markerLayer.geometries && markerLayer.geometries.length > 0) {
          markerLayer.remove(markerLayer.geometries[0].id)
        }
        markerLayer.add({
          position: evt.latLng
        });
        console.log('evt.latLng', evt.latLng, evt)
        this.latitude = evt.latLng.lat.toFixed(7)
        this.longitude = evt.latLng.lng.toFixed(7)
      })
    },
    pickedHandler () {
      this.$emit('callback', {
        latitude: this.latitude,
        longitude: this.longitude
      })
      this.isShow = false
    }
  }
}
</script>
<style lang="scss" scoped>
.map-container {
  width:100%;
  height:70vh;
}
</style>

Java端计算距离核心代码

package com.hkt.jianfa.rental.housing.manager.wx.util;

/**
 * 根据经纬度计算距离的工具类
 *
 * @author 朱治龙(i@zhuzhilong.cn)
 * @since 2021-06-29 16:22:18
 */
public class DistanceUtil {

    //地球平均半径
    private static final double EARTH_RADIUS = 6378137;

    //把经纬度转为度(°)
    private static double rad(double d) {
        return d * Math.PI / 180.0;
    }

    /**
     * 根据两点间经纬度坐标(double值),计算两点间距离,单位为米
     *
     * @param lng1 第1个坐标的经度值
     * @param lat1 第1个坐标的纬度值
     * @param lng2 第2个坐标的经度值
     * @param lat2 第2个坐标的纬度值
     * @return
     */
    public static double getDistance(double lng1, double lat1, double lng2, double lat2) {
        double radLat1 = rad(lat1);
        double radLat2 = rad(lat2);
        double a = radLat1 - radLat2;
        double b = rad(lng1) - rad(lng2);
        double 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 * EARTH_RADIUS;
        s = Math.round(s * 10000) / 10000;
        return s;
    }

    /**
     * 传入逗号分隔的两个经纬度的值计算巨鹿
     *
     * @param position1 第一个经纬度
     * @param position2 第二个经纬度
     * @return
     */
    public static double getDistance(String position1, String position2) {
        if (position1.contains(",") && position2.contains(",")) {
            String[] point1 = position1.split(",");
            String[] point2 = position2.split(",");
            return getDistance(Double.parseDouble(point1[1]), Double.parseDouble(point1[0]), Double.parseDouble(point2[1]), Double.parseDouble(point2[0]));
        }
        return 0;
    }

    /**
     * 将距离数值转换为前端显示所需的字符串信息
     *
     * @param distance
     * @return
     */
    public static String decodeDistance(double distance) {
        if (distance < 1000) {
            return "<1km";
        } else if (distance / 1000 > 100) {
            return ">100km";
        } else {
            return new Double(distance / 1000).intValue() + "km";
        }
    }

}

业务逻辑类中调用DistanceUtil方法计算距离:
kqj2i1xb.png

小程序中获取位置后,将经纬度信息传给后端计算距离及排序

kqj35a4m.png

核心代码如下:

uni.getLocation({
  type: 'gcj02',
  success: (res) => {
    this.searchForm.sort = 'distance'
    this.searchForm.location = res.latitude + ',' + res.longitude
    this.getProjects()
  },
  fail: (err) => {
    this.getProjects()
  }
})
3

评论 (0)

取消