Bootstrap

vue3移动端腾讯地图坐标拾取,获取当前定位(腾讯、高德、百度、天地图),火星坐标GCJ-02–>百度坐标BD-09,根据坐标经纬度计算两点距离的方法,点击链接打开地图导航的方法


前言

具体请参考腾讯地图开发者平台 https://lbs.qq.com/webApi

tips:
1、无论是腾讯地图还是高德、百度、天地图,都建议使用https协议访问,否则会定位异常或不精确。
2、申请地图key的步骤已省略。


地图选点(坐标拾取 移动端)

地图选点组件,类似微信中的“发送位置”功能,该组件可以让用户快速、准确地选择并确认自己的当前位置,并将相关位置信息回传给开发者。


一、调用示例

在这里插入图片描述

二、调用方法

参考 地图选点组件

tips: 在微信开发者工具中自动弹框显示地图信息是正常现象


地图选点(坐标拾取 pc端)

参考这个大佬的方法
https://blog.csdn.net/nightstar84/article/details/123770337


获取当前定位

引入封装好的JS模块,调起前端定位组件,通过封装好的接口获取位置信息

参考 地图定位组件

一、调用示例

在这里插入图片描述

1、在index.html中引入 js文件
https://mapapi.qq.com/web/mapComponents/geoLocation/v/geolocation.min.js

2、代码示例

1、调用 initMap 方法时 使用了一个定时器延后加载方法。
2、initMap 方法要在 onMounted nextTick 之后使用

// 渲染完毕后调用
onMounted(() => {
 nextTick(() => {
    initMap()
  })
})

let initMapIdx = 0;
const initMap = () => {
  if (!window.qq.maps && initMapIdx < 10) {
    setTimeout(() => {
      initMapIdx += 1;
      initMap()
    }, 500)
    return false
  }
  const geolocation = new window.qq.maps.Geolocation(
    '你申请的地图key', // 申请的腾讯地图key(必填)
    "myapp" // 申请的腾讯地图key名称(非必填,最好填一下)
  );
  // 回调的第一次参数为成功后具体的位置信息
  geolocation.getLocation(
    postion => {
      // console.log("成功", postion);
      // alert(JSON.stringify(postion))
      onComplete(postion)
    },
    err => {
      console.log("定位失败", err);
    }
  );
}

二、调用方法

参考 地图定位组件

tips: 在微信开发者工具中自动弹框显示地图信息是正常现象


other:高德地图、百度地图、天地图获取当前定位的方法

申请地图key的步骤省略
自己去对应的官网申请

一、高德地图

1、在index.html中引入 js文件
https://webapi.amap.com/maps?v=1.4.15&key=你申请的key

2、代码示例:


AMap.plugin(['AMap.Geolocation', 'AMap.ToolBar'], function () {
    // console.log(333)
    let geolocation = new AMap.Geolocation({
      enableHighAccuracy: true, //是否使用高精度定位,默认:true
      timeout: 10000, //超过10秒后停止定位,默认:5s
      buttonPosition: 'LB', //定位按钮的停靠位置
      buttonOffset: new AMap.Pixel(10, 20), //定位按钮与设置的停靠位置的偏移量,默认:Pixel(10, 20)
      zoomToAccuracy: true, //定位成功后是否自动调整地图视野到定位点
    })
    map.addControl(geolocation)
    geolocation.getCurrentPosition(function (status, result) {
      if (status == 'complete') {
        // console.log(444, result)
        // alert(JSON.stringify(result))
        // onComplete(result.position) // 成功的处理方法
      } else {
        // console.log(555, result)
        // alert(JSON.stringify(result))
        console.log('失败原因排查信息:', result.message)
      }
    })

二、百度地图(支持异步加载)

这里通过异步加载注入的方式,你也可以像上面那样在 index.html 中直接引入 js
1、创建公共文件 bdBmay.js
2、代码:

function initMap() {
  const AK = ""; //你的AK
  const BMap_URL =
    "https://api.map.baidu.com/api?v=2.0&ak=" +
    AK +
    "&s=1&callback=onBMapCallback";
  return new Promise((resolve) => {
    // 如果已加载直接返回
    if (typeof BMap !== "undefined") {
      resolve(BMap);
      return true;
    }
    // 百度地图异步加载回调处理
    window.onBMapCallback = function () {
      resolve(BMap);
    };
    // let getCurrentCityName = function () {
    //   return new Promise(function (resolve, reject) {
    //     let myCity = new BMap.LocalCity()
    //     myCity.get(function (result) {
    //       resolve(result.name)
    //     })
    //   })
    // }
    // 插入script脚本
    let scriptNode = document.createElement("script");
    scriptNode.setAttribute("type", "text/javascript");
    scriptNode.setAttribute("src", BMap_URL);
    document.body.appendChild(scriptNode);
  });
}

// 定位
function getCity() {
   initMap().then((BMap) => {
     const geolocation = new BMap.Geolocation();
     geolocation.getCurrentPosition(
       (position) => {
         let city1 = position.address.city; //获取城市信息
         //获取省份信息
         // let province = position.address.province;
         console.log(city1);
         // console.log(province)
       },
       (e) => {
         console.log(e);
         console.log("定位失败");
       },
       {
         provider: "baidu",
       }
     );
   });
 }

三、天地图

1、在index.html中引入 js文件
https://api.tianditu.gov.cn/api?v=4.0&tk=你申请的key

2、代码示例:

//创建定位对象lo
let lo = new T.Geolocation();
//开始定位
setTimeout(() => { // 加入定时器确保页面已渲染 js已加载
  lo.getCurrentPosition(fn);
}, 100);
//定位回调函数
let fn = (e) => {
  // alert(JSON.stringify(e))
  // Toast(`${res.latitude},${res.longitude}`)
  context.commit('setUserLoaction', {
    lat: e.lnglat.lat,
    lng: e.lnglat.lng
  })
  getDetailLocation(e.lnglat.lng, e.lnglat.lat);
}

// 逆地址解析
function getDetailLocation(lng, lat) {
  return new Promise(resolve => {
    fetch(`https://api.tianditu.gov.cn/geocoder?postStr={'lon':${lng},'lat':${lat},'ver':1}&type=geocode&tk=你申请的key`)
      .then((data) => {
        return data.json();
      }).then((data) => {
        if (data.status == '0') {
          // console.log(data.result)
          // alert(JSON.stringify(data.result))
          if (data.result.addressComponent) {
            alert(JSON.stringify(data.result.addressComponent))
          }
        }
        return resolve(data)
      })
  })

}

腾讯、高德、百度地图坐标系相互转换的方法(火星坐标GCJ-02–>百度坐标BD-09)


/* 火星坐标GCJ-02–>百度坐标BD-09 */
//高德坐标转百度(传入经度、纬度)
export function bd_encrypt(gg_lng, gg_lat) {
  let X_PI = Math.PI * 3000.0 / 180.0;
  let x = gg_lng,
    y = gg_lat;
  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 bd_lng = z * Math.cos(theta) + 0.0065;
  let bd_lat = z * Math.sin(theta) + 0.006;
  return {
    lng: bd_lng,
    lat: bd_lat
  };
}
//百度坐标转高德(传入经度、纬度)
export function bd_decrypt(bd_lng, bd_lat) {
  let X_PI = Math.PI * 3000.0 / 180.0;
  let x = bd_lng - 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 {
    lng: gg_lng,
    lat: gg_lat
  }
}

根据坐标经纬度计算两点距离的方法


const EARTH_RADIUS = 6378137.0; // 单位 M
const PI = Math.PI;

function getRad(d) {
  return d * PI / 180.0;
}
/* *
 * caculate the great circle distance
 * @param {number} lat1
 * @param {number} lng1
 * @param {number} lat2
 * @param {number} lng2
 */
export function getGreatCircleDistance(lat1, lng1, lat2, lng2) {
  let radLat1 = getRad(lat1);
  let radLat2 = getRad(lat2);

  let a = radLat1 - radLat2;
  let b = getRad(lng1) - getRad(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 * EARTH_RADIUS;
  s = Math.round(s * 10000) / 10000.0;

  return s;
}

// 当然,我们都知道,地球其实并不是一个真正的圆球体,而是椭球,所以有了下面的公式:
// 这个公式计算出的结果要比第一个好一些,当然,最后结果的经度实际上还取决于传入的坐标的精度。
/* *
 * approx distance between two points on earth ellipsoid
 * @param {number} lat1
 * @param {number} lng1
 * @param {number} lat2
 * @param {number} lng2
 */
export function getFlatternDistance(lat1, lng1, lat2, lng2) {
  let f = getRad((lat1 + lat2) / 2);
  let g = getRad((lat1 - lat2) / 2);
  let l = getRad((lng1 - lng2) / 2);

  let sg = Math.sin(g);
  let sl = Math.sin(l);
  let sf = Math.sin(f);

  let s, c, w, r, d, h1, h2;
  let a = EARTH_RADIUS;
  let fl = 1 / 298.257;

  sg = sg * sg;
  sl = sl * sl;
  sf = sf * sf;

  s = sg * (1 - sl) + (1 - sf) * sl;
  c = (1 - sg) * (1 - sl) + sf * sl;

  w = Math.atan(Math.sqrt(s / c));
  r = Math.sqrt(s * c) / w;
  d = 2 * w * a;
  h1 = (3 * r - 1) / 2 / c;
  h2 = (3 * r + 1) / 2 / s;

  return d * (1 + fl * (h1 * sf * (1 - sg) - h2 * (1 - sf) * sg));
}

点击链接打开地图导航的方法


/**
 * @description 点击链接跳转打开地图
 * @param {number} data.lng 经度
 * @param {number} data.lat 纬度
 * @param {number} bdData.lng 百度地图经度
 * @param {number} bdData.lat 百度地图纬度
 * @param {string} data.name 位置名称
 * @param {string} data.desc 位置详细信息(描述)
 * @param {string} dataInfo.addressKeyword 搜索的位置信息(模糊查询)
 * @param {string} dataInfo.city 城市名
 */
// 腾讯地图
`https://apis.map.qq.com/uri/v1/search?keyword=${dataInfo.addressKeyword}&region=${dataInfo.city}&referer=xingcunyi`;
`https://apis.map.qq.com/uri/v1/geocoder?coord=${data.lat},${data.lng}&name=${data.name}`
// 高德地图
`https://uri.amap.com/marker?position=${data.lng},${data.lat}&name=${data.name}&coordinate=gaode&callnative=1`
// 百度地图
`https://api.map.baidu.com/marker?location=${bdData.lat},${bdData.lng}&title=${data.name}&content=${data.desc}&output=html`


总结

腾讯地图比较适合微信h5。
高德地图在手机上表现会更好一点,提供了丰富的自定义地图。
百度地图有http的定位方法可用,会有一点误差,与其它地图使用时记得转换两种坐标系。
天地图目前是在测试阶段,功能没有以上三种齐全,定位精度偏低,存在一些坑,最大的优势是商用免费,另外3种商用都得5W左右一年。

;