关于在微信小程序内使用腾讯地图SDK 并显示相对位置

220 阅读2分钟

1.首先需要下载腾讯地图小程序SDK api lbs.qq.com/miniProgram…

image.png 把解压的文件放入项目

image.png

image.png

2.在对应的页面使用 页面中 里面的元素都要用cover-image cover-view之类的 元素不支持flex属性

<map id="map" longitude="{{longitude}}" latitude="{{latitude}}" polyline="{{polyline}}" scale="13" markers="{{markers}}" bindmarkertap="markertap" style="width:750rpx; height:99vh;">


	<cover-view slot="callout" class="p-r">
						<cover-view marker-id="1" class="callout-box ">
								<cover-view class="sanjiao"></cover-view>
								<cover-view style="display:inline-block">距您</cover-view>
								<cover-view style="color:#5234e0;display:inline-block">{{distance}}</cover-view>
								<cover-view style="display:inline-block">,</cover-view>
								<cover-view style="color:#5234e0;display:inline-block">{{duration}}</cover-view>
								<cover-view style="display:inline-block">到达</cover-view>
						</cover-view>
				</cover-view>
</map>
//引入腾讯地图服务
import QQMapWX from "../../utils/qqmap-wx-jssdk"; //腾讯地图,reverseGeocoder逆地址转码

//引入定位权限 封装的定位权限
import { $getLocation,$watchLocationBg } from "../../plugin/utils/location";
import Toast from "../../miniprogram_npm/@vant/weapp/toast/toast";

const startIcon = "../../static/icon/phone.png"//mark的图标
const endIcon = "../../static/icon/phone.png"
const postionIcon = "../../static/icon/time.png"
const QQMapSDK = new QQMapWX({
  key: "你申请的地图key"
})

onload周期调用地图api

async onLoad(options) {
    // ===========腾讯地图start=========
    //页面需要读取当前定位 没获取到自动打开授权页面 
    let res = await $getLocation();
    if (res) {
      this.setData({
        currentPoint: {
          lng: res.lng,
          lat: res.lat,
        },
queryMapRoutine      });
    }
    this.queryMapRoutine()
    // ===========腾讯地图end=========
  },

调用方法

 // 查询地图路线
  queryMapRoutine() {
    QQMapSDK.direction({
      mode: "driving", // ‘driving’(驾车)、‘walking’(步行)、‘bicycling’(骑行)、‘transit’(公交),默认:‘driving’
      // from参数不填默认当前地址
      from: this.data.fromLocation,
      to: this.data.toLocation,
      success: (res) => {
        console.log('路线规划结果', res);
        this.parseRoute(res)
      }
    })
  },
  // 解析路线,包括距离,时间,描述,路线,起止点等
  parseRoute(res) {
    //console.log(res);
    var ret = res;
    var coors = ret.result.routes[0].polyline, pl = [];
    //坐标解压(返回的点串坐标,通过前向差分进行压缩)
    var kr = 1000000;
    for (var i = 2; i < coors.length; i++) {
      coors[i] = Number(coors[i - 2]) + Number(coors[i]) / kr;
    }
    //将解压后的坐标放入点串数组pl中
    for (var i = 0; i < coors.length; i += 2) {
      pl.push({ latitude: coors[i], longitude: coors[i + 1] })
    }
    console.log(pl)
    //设置polyline属性,将路线显示出来,将解压坐标第一个数据作为起点
    this.setData({
      latitude: pl[0].latitude,
      longitude: pl[0].longitude,
      polyline: [{
        points: pl,
        color: '#6e4ddd',
        width: 4
      }]
    })
    //设定地图上的mark点
    this.setMarks()
    //获得距离
    this.getDistance()
  },
    // 设置当前点 起点终点的颜色
  setMarks() {
    let markers = [
      //起点
      {
        iconPath: startIcon,
        id: 0,
        latitude: this.data.fromLocation.latitude,
        longitude: this.data.fromLocation.longitude,
        width: 28,
        height: 28,
        zIndex: -1,
        anchor: { x: 0.5, y: 1 }
      },
      //当前位置
      {
        iconPath: postionIcon,
        id: 1,
        latitude: this.data.currentPoint.lat,
        longitude: this.data.currentPoint.lng,
        width: 28,
        height: 28,
        zIndex: -1,
        anchor: { x: 0.5, y: 1 },
        customCallout: {
          anchorY: -10,
          anchorX: 0,
          display: 'ALWAYS',
        },
        rotate:0,
      },
      //终点
      {
        iconPath: endIcon,
        id: 2,
        latitude: this.data.toLocation.latitude,
        longitude: this.data.toLocation.longitude,
        width: 28,
        height: 28,
        zIndex: -1,
        anchor: { x: 0.5, y: 1 }
      }]
    this.setData({ markers: markers })
  },
  //查询当前位置和终点间的距离
 async getDistance(lat,lng) {
  if(lat && lng){
    this.setData({
      currentPoint: {
        lng: lng,
        lat: lat,
        },
      },
    );
  }
    QQMapSDK.direction({
      mode: "driving", // ‘driving’(驾车)、‘walking’(步行)、‘bicycling’(骑行)、‘transit’(公交),默认:‘driving’
      from: {
        latitude: this.data.currentPoint.lat,
        longitude: this.data.currentPoint.lng
      },
      to: this.data.toLocation,
      success: (res) => {
        this.setNursePostion(res)
      }
    })
  },
  //设置当前距离 剩余时间 一分钟刷新一次
 async setNursePostion(res) {
    let data = res.result.routes[0]
    //当前剩余距离时间计算
    this.setData({
      distance:data.distance < 1000 ?
      `${data.distance}m` :
      `${(data.distance / 1000).toFixed(2)}km`,
      duration:data.duration < 60 ?
      `${data.duration}分钟` :
      `${parseInt(data.duration / 60)}小时${data.duration % 60}分钟`,
    })
    //地图上 当前位置更新
    //计算当前路线下的行驶方向
    let rotate = this.formatterRotate(data.steps[0].dir_desc)
    let markers = this.data.markers
    let currentObj = markers[1]
    currentObj.latitude = this.data.currentPoint.lat
    currentObj.longitude = this.data.currentPoint.lng
    currentObj.rotate = rotate
    markers[1] = currentObj
    this.setData({ markers: markers })
  },

3封装的定位权限js

import { $msg } from './index'
import { getSetting, openSetting } from './setting'

function getLocation() {
  return new Promise((resolve) => {
    wx.getLocation({
      success: ({ longitude: lng, latitude: lat }) => resolve({ lng, lat }),
      fail: () => {
        wx.showModal({
          cancelText: '取消',
          confirmText: '前往设置',
          content: '获取权限失败,需要获取您的地理位置才能为您提供更好的服务!是否授权获取地理位置?',
          editable: false,
          showCancel: true,
          title: '温馨提示',
          success: (e) => {
            if(e.confirm){ wx.openSetting()}
          },
          fail: () => {},
        })
      }
    })
  })
}

function chooseLocation() {
  return new Promise((resolve) => {
    wx.chooseLocation({
      success: ({ address, name }) => resolve(address + name),
      fail: () => {
        wx.showModal({
          cancelText: '取消',
          confirmText: '前往设置',
          content: '获取权限失败,需要获取您的地理位置才能为您提供更好的服务!是否授权获取地理位置?',
          editable: false,
          showCancel: true,
          title: '温馨提示',
          success: (e) => {
            if(e.confirm){ wx.openSetting()}
          },
          fail: () => {},
        })
      }
    })
  })
}

function watchLocationBg(){
  return new Promise((resolve) => {
    wx.startLocationUpdateBackground({
      success:  () => {console.log('开启后台定位', res)},
      fail: () => {
        wx.showModal({
          cancelText: '取消',
          confirmText: '前往设置',
          content: '获取权限失败,需要获取您的地理位置才能为您提供更好的服务!是否授权获取地理位置?',
          editable: false,
          showCancel: true,
          title: '温馨提示',
          success: (e) => {
            if(e.confirm){ wx.openSetting()}
          },
          fail: () => {},
        })
      }
    })
  })
}

/**
 * 对外获取经纬度的方法
 */
export let $getLocation = () => fixedSetting(getLocation)

/**
 * 对外选择地址的方法
 */
export let $chooseLocation = () => fixedSetting(chooseLocation)
/**
 * 开启后台监控定位 
 * 使用该权限定位之
 * 这个方法使用后对应页面能监听位置变化
 */
export let $watchLocationBg = () => fixedSetting(watchLocationBg)
/**
 * 统一处理授权问题
 */
async function fixedSetting(callback) {
  //先查看是否有此权限
  let res = await getSetting('scope.userLocation')
  //如果有权限,或者第一次请求此权限,则正常获取位置
  console.log("权限",res);
  if (res || res === undefined) return await callback()
  else {
    wx.showModal({
      cancelText: '取消',
      confirmText: '前往设置',
      content: '获取权限失败,需要获取您的地理位置才能为您提供更好的服务!是否授权获取地理位置?',
      editable: false,
      showCancel: true,
      title: '温馨提示',
      success: (e) => {
        if(e.confirm){ wx.openSetting()}
      },
      fail: () => {},
    })
    // //如果之前请求权限被拒绝过,则打开设置页
    // console.log("定位未授权,判断未授权打开授权页需要点击事件触发");
    // let res1 = await openSetting('scope.userLocation')
    // //根据设置页的结果,再次获取定位
    // console.log(res1);
    // if (res1) return await callback()
    // else {}
  }
}

4app.json内需要的权限

"permission": {
    "scope.userLocation": {
      "desc": "你的位置信息将用于小程序定位"
    }
  },
  "requiredPrivateInfos": [
    "getLocation",
    "startLocationUpdateBackground",
    "onLocationChange"
  ],