vue2实现高德地图 JSAPI 2.0可拖拽的路线规划(DragRoute)组件实现对每个经过点设置不同的经过点名称

问题记录

vue2实现高德地图 JSAPI 2.0可拖拽的路线规划(DragRoute)组件实现对每个经过点设置不同的经过点名称

官方文档及示例

DragRoute相关API

API中没有任何方法让我们对每个经过点进行设置,所以只能我们自己实现

image-20230317163350154

实现效果如下:

image-20230317154134066

集成DragRoute到自己的组件

  1. 设置变量

    image-20230317154937284

  2. 引入DragRoute组件

    image-20230317155022084

  3. image-20230317155317539

以上步骤完成后就集成了DragRoute组件

对每个经过点设置不同的经过点名称

image-20230317160015595

_path中存储的数据如下图是一个LngLat对象,但是转换为json字符串后就是一个经纬度数组

image-20230317160642232

image-20230317160844078

父组件中

image-20230317160438249

   getRoutePath(childValue){
     this.form.routePathString=JSON.stringify(childValue)
   },

将数据库中的数据加载到重新加载到route中

image-20230317161550409

此处我将DragRoute的初始化单独抽取成了一个方法,

image-20230317161507500

此时其实已经完成了目的功能

但是存储到后端后再次加载地图所有的经过点的content都是一样的效果如下:

这是因为我们的路径点的content都在初始化时都被midMarkerOptions设置为相同的了

Snipaste_2023-03-15_16-41-59

解决路径点content相同问题

主要的思路是将route中的marker都重新修改content后再重新加载就可以实现了

image-20230317162434136

updateMindPointContext: function () {
        let pathList = this.route._list
        console.log(pathList)
        let startPoint = pathList[0]
        let endPoint = pathList[pathList.length - 1]
        let mindPoint = []
        pathList.forEach(item => {
          if (item.id != startPoint.id && item.id != endPoint.id) {
            mindPoint.push(item)
          }
        })
        let count = 1
        mindPoint.forEach(item => {
          item.marker._opts.label.content = '经过点' + count
          count++
          item.marker.setContent('')//需要set一下上面代码才会生效
        })
        pathList = []
        pathList.push(startPoint)
        pathList.push(...mindPoint)
        pathList.push(endPoint)
        this.route._list = pathList
      },

然后我们在每次初始化时都调用此方法就解决了

image-20230317162511361

组件代码

<template>
  <div>
    <a-row>
      <div id="container"></div>
      <div class='input-card-ControlBar' v-show="visible">
        <div class="input-item">
          <a-checkbox @change="toggleScale" :checked="toggleScaleCheck">比例尺</a-checkbox>
        </div>

        <div class="input-item">
          <a-checkbox @change="toggleToolBar" :checked="toggleToolBarCheck">工具条</a-checkbox>
        </div>

        <div class="input-item">
          <a-checkbox @change="toggleControlBar" :checked="toggleControlBarCheck">工具条方向盘</a-checkbox>
        </div>

        <div class="input-item">
          <a-checkbox @change="toggleOverViewShow" :checked="toggleOverViewShowCheck">显示鹰眼</a-checkbox>
        </div>
      </div>
      <div class="input-card-MouseTool" style='width: 24rem;' v-show="visible">
        <div class="input-item">
          左击获取经纬度: <input type="text" :value="clickValue">
        </div>

        <div class="input-item">
          <a-radio-group v-model="drawOptionValue" :options="drawOptions" @change="onChangeDrawOption"/>
        </div>
        <div class="input-item" style="margin-top: 10px">
          <a-button type="primary" size="small" style="width: 90px" @click="clearMap">
            清除
          </a-button>
          <a-button type="primary" size="small" style="margin-left: 10px;width: 90px" @click="closeDram">
            关闭绘图
          </a-button>
        </div>
      </div>
    </a-row>
  </div>

</template>

<script>
  //这里可以导入其他文件(比如: 组件, 工具 js, 第三方插件 js, json文件, 图片文件等等)
  //例如: import 《组件名称》 from '《组件路径》 ';

  import AMapLoader from "@amap/amap-jsapi-loader";
  // 设置安全密钥
  window._AMapSecurityConfig = {
    securityJsCode: 'xxxx',
  }
  export default {
    name: 'MapContainer',
    //import 引入的组件需要注入到对象中才能使用
    components: {},
    props: {
      visible: Boolean,
      drewData: Array,
      routePathP: Array,
    },
    data() {
      //这里存放数据
      return {
        AMap: null,
        //此处不声明 map 对象,可以直接使用 this.map赋值或者采用非响应式的普通对象来存储。
        map: null,
        mouseTool: null,
        //监听draw事件可获取画好的覆盖物
        overlays: [],
        auto: null,
        placeSearch: null,
        drawOptionValue: '',
        drawOptions: [
          {label: '画点', value: 'marker'},
          {label: '画折线', value: 'polyline'},
          {label: '画多边形', value: 'polygon'},
          {label: '画矩形', value: 'rectangle'},
          {label: '画圆', value: 'circle'},
          {label: '路径规划', value: 'routePath'},
          {label: '获取经纬度', value: 'position'},
        ],
        //--地图控件 --
        toggleOverViewShowCheck: true,
        toggleControlBarCheck: true,
        toggleToolBarCheck: true,
        toggleScaleCheck: true,
        scale: null,
        toolBar: null,
        controlBar: null,
        overView: null,
        //坐击经纬度
        clickValue: '',
        //可拖拽路线规划
        route: null,
        routePath: this.routePathP,
        startAndEnd:[],
      };
    },
    //计算属性 类似于 data 概念
    computed: {},
    //监控 data 中的数据变化
    watch: {
      overlays(newVal, oldVal) {
        this.$emit('getOverlaysValue', newVal)
      },
      drewData(newValue, oldValue) {
        this.mountDrewData()
      },
      routePathP(newValue, oldValue){
        this.routePath=this.routePathP;
        this.initPathAssign(this.AMap)
      },
      startAndEnd(newValue, oldValue){
        if (this.startAndEnd.length==2){
          this.routePath=this.startAndEnd.map(item=>{
            return item.getPosition()
          })
          console.log(this.routePath)
          this.initPathAssign(this.AMap)
          this.startAndEnd.forEach(item=>{
            item.remove()
          })
          this.startAndEnd=[]
        }
      }
    },
    //方法集合
    methods: {
      toggleOverViewShow(e) {
        this.toggleOverViewShowCheck = e.target.checked
        if (e.target.checked) {
          this.overView.show();
        } else {
          this.overView.hide();
        }
      },
      toggleControlBar(e) {
        this.toggleControlBarCheck = e.target.checked
        if (e.target.checked) {
          this.controlBar.show()
        } else {
          this.controlBar.hide()
        }
      },
      toggleToolBar(e) {
        this.toggleToolBarCheck = e.target.checked
        if (e.target.checked) {
          this.toolBar.show();
        } else {
          this.toolBar.hide();
        }
      },
      toggleScale(e) {
        this.toggleScaleCheck = e.target.checked
        if (e.target.checked) {
          this.scale.show();
        } else {
          this.scale.hide();
        }
      },
      closeDram() {
        this.mouseTool.close(true)
        this.drawOptionValue = ''
      },
      clearMap() {
        this.map.remove(this.overlays)
        this.overlays = [];
        this.route.destroy()
        this.$emit('getRoutePath', [])
        // this.$emit('getOverlaysValue', this.overlays)
      },
      onChangeDrawOption(e) {
        console.log('radio checked', e.target.value);
        this.draw(e.target.value)
      },
      initMapTool() {
        this.scale = new AMap.Scale();
        this.toolBar = new AMap.ToolBar({
          position: {
            top: '110px',
            right: '40px'
          }
        });
        this.controlBar = new AMap.ControlBar({
          position: {
            top: '10px',
            right: '10px',
          }
        });
        this.overView = new AMap.HawkEye({
          position: {
            top: '10px',
            left: '10px',
          },
          opened: false
        });
        this.map.addControl(this.scale);
        this.map.addControl(this.toolBar);
        this.map.addControl(this.controlBar);
        this.map.addControl(this.overView);
      },
      initMouseTool(AMap) {
        this.mouseTool = new AMap.MouseTool(this.map);
        // 监听draw事件可获取画好的覆盖物
        this.mouseTool.on('draw', function (e) {
          this.overlays.push(e.obj);
        }.bind(this))
        //为地图注册click事件获取鼠标点击出的经纬度坐标
        this.map.on('click', function (e) {
          if (this.drawOptionValue=='routePath'){
            if (this.startAndEnd.length==0){
              let start = new AMap.Marker({
                icon: "//webapi.amap.com/theme/v1.3/markers/n/start.png",
                position: [e.lnglat.getLng(),e.lnglat.getLat()],
                offset: new AMap.Pixel(-13, -30)
              });
              start.setMap(this.map);
              this.startAndEnd.push(start)
            }else if (this.startAndEnd.length==1){
              let end = new AMap.Marker({
                icon: "//webapi.amap.com/theme/v1.3/markers/n/end.png",
                position: [e.lnglat.getLng(),e.lnglat.getLat()],
                offset: new AMap.Pixel(-13, -30)
              });
              end.setMap(this.map);
              this.startAndEnd.push(end)
            }
          }
          if (this.drawOptionValue=='position'){
            this.clickValue = e.lnglat.getLng() + ',' + e.lnglat.getLat()
          }

        }.bind(this));
        this.mountDrewData()

      },
      mountDrewData(){
        if (this.drewData!=null){
          this.drewData.forEach(item => {
            this.drew(item.overlayType, item.opts)
          })
        }
      },

      updateMindPointContext: function () {
        let pathList = this.route._list
        console.log(pathList)
        let startPoint = pathList[0]
        let endPoint = pathList[pathList.length - 1]
        let mindPoint = []
        pathList.forEach(item => {
          if (item.id != startPoint.id && item.id != endPoint.id) {
            mindPoint.push(item)
          }
        })
        let count = 1
        mindPoint.forEach(item => {
          item.marker._opts.label.content = '经过点' + count
          count++
          item.marker.setContent('')//需要set一下上面代码才会生效
        })
        pathList = []
        pathList.push(startPoint)
        pathList.push(...mindPoint)
        pathList.push(endPoint)
        this.route._list = pathList
      },
      initPathAssign (AMap) {
        // this.routePath.push([104.050025, 30.6683]);
        // this.routePath.push([104.044078, 30.671447]);

        this.route = new AMap.DragRoute(this.map, this.routePath, AMap.DrivingPolicy.LEAST_FEE, {
          midMarkerOptions: {
            // icon: '//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-1.png',
            label: {
              content: '路径点'+(this.routePath.length-1)
            }
          }
        }); //构造拖拽导航类
        this.route.search(); //查询导航路径并开启拖拽导航
        this.route.on('addway', function (e) {
          // e.target.midMarkerOptions.icon= '//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-'+(this.route.getWays().length+1)+'.png'
          e.target.midMarkerOptions.label.content = '路径点' + (this.route.getWays().length + 1)
          this.$emit('getRoutePath', this.route._path)
        }.bind(this))
        this.updateMindPointContext();
      },
      initMap() {
        AMapLoader.load({
          key: "xxxxxx",             // 申请好的Web端开发者Key,首次调用 load 时必填
          version: "2.0",      // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
          "plugins": [
            "AMap.Scale",
            "AMap.HawkEye",
            "AMap.ToolBar",
            "AMap.AutoComplete",
            "AMap.PlaceSearch",
            "AMap.ControlBar",
            "AMap.MouseTool",
            "AMap.DragRoute"],         // 需要使用的的插件列表,如比例尺'AMap.Scale'等
        }).then((AMap) => {
          this.AMap=AMap
          this.map = new AMap.Map("container", {  //设置地图容器id
            viewMode: "2D",  //  是否为3D地图模式
            zoom: 13,   // 初始化地图级别
            center: [104.065735, 30.659462], //中心点坐标  成都
            resizeEnable: true
          });
          this.initMouseTool(AMap);
          //地图工具
          this.initMapTool();
          //路径规划工具初始化
          this.initPathAssign(AMap);


        }).catch(e => {
          console.log(e);
        })
      },
      draw(type) {
        switch (type) {
          case 'marker': {
            this.mouseTool.marker({
              //同Marker的Option设置
            });
            break;
          }
          case 'polyline': {
            this.mouseTool.polyline({
              strokeColor: '#80d8ff'
              //同Polyline的Option设置
            });
            break;
          }
          case 'polygon': {
            this.mouseTool.polygon({
              fillColor: '#00b0ff',
              strokeColor: '#80d8ff'
              //同Polygon的Option设置
            });
            break;
          }
          case 'rectangle': {
            this.mouseTool.rectangle({
              fillColor: '#00b0ff',
              strokeColor: '#80d8ff'
              //同Polygon的Option设置
            });
            break;
          }
          case 'circle': {
            this.mouseTool.circle({
              fillColor: '#00b0ff',
              strokeColor: '#80d8ff'
              //同Circle的Option设置
            });
            break;
          }
        }
      },
      drew(type, opts) {
        switch (type) {
          case 'marker': {
            opts.map = this.map
            let o = new AMap.Marker(opts);
            this.overlays.push(o);
            break;
          }
          case 'polyline': {
            opts.map = this.map
            let o = new AMap.Polyline(opts)
            this.overlays.push(o);
            break;
          }
          case 'polygon': {
            opts.map = this.map
            let o = new AMap.Polygon(opts)
            this.overlays.push(o);
            break;
          }
          case 'rectangle': {
            opts.map = this.map
            let o = new AMap.Rectangle(opts)
            this.overlays.push(o);
            break;
          }
          case 'circle': {
            opts.map = this.map
            let o = new AMap.Circle(opts)
            this.overlays.push(o);
            break;
          }
        }
      }
    },
    //生命周期 - 创建完成(可以访问当前 this 实例)
    created() {
    },
    //生命周期 - 挂载完成(可以访问 DOM 元素)
    mounted() {
      this.initMap();
    },
    //生命周期 - 创建之前
    beforeCreate() {
    },
    //生命周期 - 挂载之前
    beforeMount() {
    },
    //生命周期 - 更新之前
    beforeUpdate() {
    },
    //生命周期 - 更新之后
    updated() {
    },
    //生命周期 - 销毁之前
    beforeDestroy() {
    },
    //生命周期 - 销毁完成
    destroyed() {
    },
    //如果页面有 keep-alive 缓存功能, 这个函数会触发
    activated() {
    },
  }
</script>

<style scoped>
  #container {
    padding: 0px;
    margin: 0px;
    width: 100%;
    height: 800px;
  }

  .input-item {
    height: 2.2rem;
  }

  .input-card-ControlBar {
    display: flex;
    flex-direction: column;
    min-width: 0;
    word-wrap: break-word;
    background-color: #fff;
    background-clip: border-box;
    border-radius: .25rem;
    width: 10rem;
    border-width: 0;
    border-radius: 0.4rem;
    box-shadow: 0 2px 6px 0 rgba(114, 124, 245, .5);
    position: fixed;
    bottom: 12rem;
    right: 2rem;
    -ms-flex: 1 1 auto;
    flex: 1 1 auto;
    padding: 0.75rem 1.25rem;
  }

  .input-card-MouseTool {
    display: flex;
    flex-direction: column;
    min-width: 0;
    word-wrap: break-word;
    background-color: #fff;
    background-clip: border-box;
    border-radius: .25rem;
    width: 10rem;
    border-width: 0;
    border-radius: 0.4rem;
    box-shadow: 0 2px 6px 0 rgba(114, 124, 245, .5);
    position: fixed;
    bottom: 12rem;
    right: 12rem;
    -ms-flex: 1 1 auto;
    flex: 1 1 auto;
    padding: 0.75rem 1.25rem;
  }
</style>

父组件使用示例代码

<template>
  <Map-Container
    ref="mapChild"
    :visible="drawerVisible"
    :drewData="drewData"
    :routePathP="routePath"
    @getOverlaysValue="getOverlaysValue"
    @getRoutePath="getRoutePath">

  </Map-Container>
</template>

<script>
  import MapContainer from "@/pages/components/map/MapContainer";
  export default {
    name: 'Post',
    components: { MapContainer},
    data() {
      return {
        drewData: [],
        form: {
          overlays: '',
          createBy: '',
          routePathString: '',
        },
        routePath: [],
      }
    },
    methods: {
      getRoutePath(childValue){
        this.form.routePathString=JSON.stringify(childValue)
      },
      getOverlaysValue: function (childValue) {

        let overlaysString = []
        overlaysString = childValue.map(item => {
          switch (item.className) {
            case 'AMap.Marker': {
              item._opts.map = null
              let opts = item._opts
              let overlay = {
                overlayType: 'marker',
                opts: opts
              }
              return overlay
            }
            case 'Overlay.Polyline': {
              item._opts.map = null
              let opts = item._opts
              let overlay = {
                overlayType: 'polyline',
                opts: opts
              }
              return overlay
            }
            case 'Overlay.Polygon': {
              item._opts.map = null
              let opts = item._opts
              let overlay = {
                overlayType: 'polygon',
                opts: opts
              }
              return overlay
            }
            case 'Overlay.Rectangle': {
              item._opts.map = null
              let opts = item._opts
              let overlay = {
                overlayType: 'rectangle',
                opts: opts
              }
              return overlay
            }
            case 'Overlay.Circle': {
              item._opts.map = null
              let opts = item._opts
              let overlay = {
                overlayType: 'circle',
                opts: opts
              }
              return overlay
            }
          }
        })
        this.form.overlaysString = JSON.stringify(overlaysString)
      },
    }
  }
</script>

<style lang="less" scoped>
  .search {
    margin-bottom: 54px;
  }

  .fold {
    width: calc(100% - 216px);
    display: inline-block
  }

  .operator {
    margin-bottom: 18px;
  }

  @media screen and (max-width: 900px) {
    .fold {
      width: 100%;
    }
  }
</style>
  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
Vue2中,使用高德地图进行路线规划设置途径的方法如下: 首先,在代码中导入AMapManager和AMap.Walking插件。创建一个AMapManager实例,并初始化地图对象map。 然后,在需要进行路线规划的方法中,使用AMap.Walking创建一个步行对象walking,并传入地图对象map和路线规划结果展示的面板panel。 接下来,调用walking.search方法,传入起和终的经纬度坐标,以及途径的经纬度坐标(可选),并在回调函数中处理路线规划结果。 最后,返回该方法,以便在Vue组件中调用。 示例代码如下: ```javascript import { AMapManager } from "vue-amap"; window.amapManager = new AMapManager(); window.map = null; // ... foot() { var that = this; map = this.amapManager.getMap(); AMap.plugin(\["AMap.Walking"\], function () { var walking = new AMap.Walking({ map: map, panel: "panel", }); that.clear(); // 清除所有位和路线 walking.search( new AMap.LngLat(起经度, 起纬度), new AMap.LngLat(终经度, 终纬度), function (status, result) { if (status === "complete") { if (result.routes && result.routes.length) { // 处理路线规划结果 } } else { // 处理错误情况 } } ); }); return; }, ``` 请注意,起和终的经纬度需要替换为实际的数值。途径的经纬度是可选的,如果不需要设置途径,可以省略该参数。 希望对你有所帮助! #### 引用[.reference_title] - *1* *2* *3* [关于vue使用高德地图vue-amap实现路径规划](https://blog.csdn.net/foreverlailai/article/details/109166087)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值