Vue 2.x 使用高德地图JS API 2.0加载起点终点路径轨迹

背景

最近在开发 H5 页面,需求是在地图中显示行驶轨迹,在 H5 中调起地图app,轨迹经纬度列表由接口提供,坐标系为国际标准的坐标体系 WGS84,刚开始并未注意这个坐标系问题,在使用中发现位置加载出来会存在定位偏移,记录一下使用过程

需求

  1. 在地图中显示行驶轨迹,自定义标记点图标
    地图厂商使用高德地图,使用目前最新的高德地图JSAPI 2.0

  2. 在自己的 H5 中调起多个地图app,显示标记点位置
    由于地图 APP 并不支持在自己的网页中直接打开,因此需要通过地图 URI API 调用厂商H5地图,在厂商H5地图调起地图app

参考文章

高德地图 JSAPI 2.0

地图厂商 URL API,调起H5地图:
高德地图
百度地图
腾讯地图
h5跳转到移动端地图网页打开地图app

实现过程

H5 UI 框架使用 Vant
详细高德地图引入方式参考高德地图文档
这里记录一下主要内容

在 html 文件中引入地图 js

<script src="https://webapi.amap.com/maps?v=2.0&key=申请的key值&plugin=AMap.Driving"></script>

主页面

// index.vue
<template>
  <div class="index">
    <template >
      <v-map :data="dataList"></v-map>
      <v-detail :statrLocation="statrLocation" :endLocation="endLocation"/>
    </template>
  </div>
</template>

<script>
import Map from './mMap.vue'  // 地图
import Detail from './detail.vue'

export default {
      
      
  name: 'index',
  data() {
      
      
    return {
      
      
      dataList: [],
      statrLocation: {
      
      },
      endLocation: {
      
      },
    }
  },
  components: {
      
      
    "v-map": Map,
    "v-detail": Detail
  },
  mounted() {
      
      
  	this.dataList = [
      {
      
      
        longitude: 116.478346,
        latitude: 39.997361
      },
      {
      
      
        longitude: 116.402796,
        latitude: 39.936915
      }
    ]
    this.statrLocation = this.dataList[0]
    this.endLocation = this.dataList[this.dataList.length-1]
  },
  methods: {
      
      
    
  }
};
</script>
<style scoped lang="scss">
.index {
      
      
  position: relative;
  width: 100%;
  height: 100%;
  background: #fcf9f2;
}
</style>

地图组件

// mMap.vue
<template>
  <div class="m-map">
    <div id="map-box"></div>
  </div>
</template>
<script>

export default {
      
      
  props: ['data'],
  data() {
      
      
    return {
      
      
      map: {
      
      },
      lineArr: [],
    };
  },
  created() {
      
      
    this.initMap()
  },
  methods: {
      
      
    initMap() {
      
      
      this.$nextTick(() => {
      
      
        this.map = new AMap.Map('map-box', {
      
      
          resizeEnable: true, //是否监控地图容器尺寸变化
          zoom: 14, //初始化地图层级
          center: [116.397428, 39.90923], //初始化地图中心点
          animateEnable: true// 地图平移过程中是否使用动画
        });

        if(this.lineArr.length) {
      
      
          this.drawLine()  //绘制路线
        }
      });
    },
    drawLine(){
      
      
      AMap.convertFrom(this.lineArr, 'gps', (status, result) => {
      
      
        if (result.info === 'ok') {
      
      
          const paths = result.locations;

          this.map.clearMap()

          this.startMarker = new AMap.Marker({
      
      
            map: this.map,
            position: paths[0],  //起点经纬度
            icon: new AMap.Icon({
      
                  
              image: require('@/assets/img/icon/icon-start.png'),
              size: new AMap.Size(120, 120),  //图标所处区域大小
              imageSize: new AMap.Size(120,120) //图标大小
            }),   //起点ico
            offset: new AMap.Pixel(-60, -60),
            autoRotation: true,
            // angle:-90,
          });
          
          this.endMarker = new AMap.Marker({
      
      
            map: this.map,
            position: paths[paths.length-1], //终点经纬度
            icon: new AMap.Icon({
      
                  
              image: require('@/assets/img/icon/icon-end.png'),
              size: new AMap.Size(60, 60),  //图标所处区域大小
              imageSize: new AMap.Size(60,60) //图标大小
            }),   //终点ico
            offset: new AMap.Pixel(-30, -30),
            autoRotation: true,
          });

          // 绘制轨迹
          var polyline = new AMap.Polyline({
      
      
            map: this.map,
            path: paths,
            showDir: true,
            strokeColor: '#28F', //线颜色
            // strokeOpacity: 1,     //线透明度
            strokeWeight: 6, //线宽
            // strokeStyle: "solid"  //线样式
          });
          this.map.add([this.startMarker, this.endMarker]);
          this.map.setFitView();  //自适应缩放级别
        }
      })

    }
  },
  watch: {
      
      
    data: {
      
      
      handler(newValue, oldValue) {
      
      
        this.lineArr = [];
        if(newValue.length) {
      
      
          newValue.map((item, index) => {
      
      
            if( item.longitude != null && item.latitude != null ) {
      
      
              this.lineArr.push(new AMap.LngLat(item.longitude,item.latitude));
            }
          });
          this.drawLine();
        }
      },
      immediate: true
    },
  },
};
</script>
<style scoped lang ="scss">
@import '@/assets/scss/mixin.scss';
.m-map {
      
      
  width: 100%;
  height: 100vh;
  #map-box {
      
      
    width: 100%;
    height: 100%;
  }
}
</style>

代码解析

在使用中发现标记点位置显示不对,存在一定的偏移,怀疑是坐标系问题,看文档查了一下其他坐标转高德坐标方法,参考了这篇坐标变换文章,还可以实现批量转换。

在绘制轨迹之前先转换为高德坐标,然后再删除地图上所有的覆盖物,

AMap.convertFrom(this.lineArr, 'gps', (status, result) => {
    
    
  if (result.info === 'ok') {
    
    
	const paths = result.locations;
	
	this.map.clearMap()
	
	// ...
  }
})

在查询时也找到了一个处理地理坐标系的js库gcoord,用来修正百度地图、高德地图及其它互联网地图坐标系不统一的问题。

应该也可以,不过我还没有尝试。

调起地图H5 组件

// detail.vue
<template>
  <div class="m-detail-box">
    <div class="m-btn-wrapper">
      <van-button class="open-btn" round  @click="openShow = true">导航至车辆当前位置</van-button>
    </div>
    <van-action-sheet 
      class="m-sheet-box"
      v-model="openShow" 
      :actions="actions" 
      cancel-text="取消"
      close-on-click-action
      @select="onSelect" 
    />
  </div>
</template>

<script>
import {
      
      
  Toast
} from 'vant';

export default {
      
      
  props: {
      
      
    statrLocation: {
      
      
      type: Object,
      default: () => ({
      
      })
    },
    endLocation: {
      
      
      type: Object,
      default: () => ({
      
      })
    },
  },
  data() {
      
      
    return {
      
      
      openShow: false,
      actions: [
      	{
      
       name: '使用苹果地图导航', value: 'iosamap', color: '#007AFF' }, 
        {
      
       name: '使用百度地图导航', value: 'bmap', color: '#007AFF' }, 
        {
      
       name: '使用高德地图导航', value: 'amap', color: '#007AFF' }
      ],
    }
  },
  filters: {
      
      
    
  },
  mounted() {
      
      
    
  },
  methods: {
      
      
    onSelect(item) {
      
      
      this.openShow = false;
      let startLocation = this.startLocation
      let endLocation = this.endLocation
      
      if (endLocation.longitude && endLocation.latitude) {
      
      
        let url = ''
        switch (item.value) {
      
      
          case 'iosamap':
            url = `iosamap://navi?sourceApplication=applicationName&backScheme=applicationScheme&poiname=${ 
        location}&poiid=BGVIS&lat=${ 
        endLocation.latitude}&lon=${ 
        endLocation.longitude}&dev=1&style=2`
            break;
          case 'bmap':
            // 单点标注
            url = `http://api.map.baidu.com/marker?location=${ 
        endLocation.latitude},${ 
        endLocation.longitude}&title=车辆位置&content=实时定位&output=html&coord_type=wgs84&src=webapp.baidu.openAPIdemo`
            
            // 路径规划
            // url = `http://api.map.baidu.com/direction?origin=latlng:${startLocation.latitude},${startLocation.longitude}|name:我的位置&destination=latlng:${endLocation.latitude},${endLocation.longitude}|name:实时定位&mode=driving&coord_type=wgs84&src=webapp.baidu.openAPIdemo`
            break;
          case 'amap':
            // 单点标注
            url = `https://uri.amap.com/marker?position=${ 
        endLocation.longitude},${ 
        endLocation.latitude}&name=实时定位&src=mypage&coordinate=wgs84&callnative=1`

            // 路径规划
            // url = `https://uri.amap.com/navigation?from=${startLocation.longitude},${startLocation.latitude},我的位置&to=${endLocation.longitude},${endLocation.latitude},实时定位&mode=car&policy=1&coordinate=wgs84&callnative=1`
            break;
        }
        window.open(url)
      } else {
      
      
        Toast({
      
      
          message: '暂无车辆定位',
          type: 'fail',
        })
      }
    },
  },
  beforeDestroy() {
      
      
    clearInterval(this.timer)
  }
}
</script>
<style scoped lang="scss">
@import "@/assets/scss/mixin.scss";

.m-detail-box {
      
      
  position: absolute;
  bottom: 0;
  padding: 20px 0 0;
  border-radius: 20px 20px 0px 0px;
  width: 100%;
  background: #FEFFFE;
  box-shadow: 0 4px 40px 4px rgba(135, 119, 145, 0.36);
  z-index: 160;

  .van-cell-group {
      
      
    &::after {
      
      
      border: none;
    }
  }
  
  .van-cell {
      
      
    padding: 12px 24px;
    font-size: 16px;
    font-weight: 600;

    &::after {
      
      
      left: 24px;
      right: 24px;
    }

    .van-cell__title {
      
      
      flex: none;
      color: #757AB5;
    }

    .van-cell__value {
      
      
      color: #292929;
    }
  }

  .m-btn-wrapper {
      
      
    border-top: 1px solid #EFF2F9;
    background: #FFF;

    .open-btn {
      
      
      display: block;
      margin: 10px auto;
      padding: 14px;
      width: 90%;
      font-size: 18px;
      color: #FEFFFE;
      background: #85D4D9;
    }
  }

  /deep/.van-overlay {
      
      
    background: rgba(33, 34, 51, 0.5);
  }

  .m-sheet-box {
      
      
    padding: 0 8px;
    background: transparent;

    .van-action-sheet__content {
      
      
      border-radius: 14px;
      background: rgba(255, 255, 255, 0.92);
    }

    .van-action-sheet__gap {
      
      
      height: 20px;
      background: transparent;
    }

    .van-action-sheet__cancel {
      
      
      margin-bottom: 20px;
      border-radius: 14px;
      font-size: 20px;
      color: #007AFF;
      background: rgba(255, 255, 255, 0.92);
    }
  }
}
</style>

打开地图 H5 时需要指定坐标系参数,不指定的话在地图H5 中的定位也会存在偏移
截图
在这里插入图片描述

记录

之前写的时候没有发现定位偏移问题,重新整理记录一下

猜你喜欢

转载自blog.csdn.net/sinat_35272898/article/details/121400275