likes
comments
collection
share

腾讯地图api,根据路线画自定义箭头

作者站长头像
站长
· 阅读数 29

我遇到的情况:

1、使用腾讯地图画出路径,并在地图上表示方向(也就是箭头指向)

我查了很多的资料,并没有详细的结论,我按照api给的方法,我自定义做出的效果vue+element+腾讯地图API,(仅供参考)效果图如下:腾讯地图api,根据路线画自定义箭头

思路

1、首先看是否跟我使用的方法声明Map一致的方法,腾讯地图的JavaScript API GL的api(如有不同,可以看逻辑,逻辑是一样的,但是需要自己去专研下代码)https://lbs.qq.com/webApi/jav...2、如果看到这里,那我先讲下逻辑,我之前考虑过方案:(1)地图自带的线段带的箭头指向(跟实际需求不符) ,而且,箭头不能大于具体宽度,这样我们没办法扩展,果然放弃了(希望腾讯地图api,这里可以改善下)

这时示例地址:https://lbs.qq.com/webDemoCen...这是api地址:https://lbs.qq.com/webApi/jav...

腾讯地图api,根据路线画自定义箭头

(2)自定义DOM覆盖物(DOMOverlay)这是百度搜索最多的方案,但是我看过,可以做到,声明img结构(img就是箭头的图片),按照img旋转不同的角度所得到的,但是会出现一种bug,就是不会随着地图缩放而进行变化,这就很恼火了,所以我就没考虑(测试肯定给我提bug)(3)这种目前我使用的一种,根据两点的坐标,判断角度、拿到箭头的三角坐标给画两条线,结合成箭头形状,(说白点:就是跟画线一样,画出来的箭头)(4)根据画多边形,进行绘制,但是原理都是一样的,先找到箭头的三角坐标,之后进行处理,需要看具体的需求,(如果是箭头是覆盖有颜色的,那就先拿到坐标,进行多边形绘制,效果也能实现)。重点:拿到箭头的三个角的坐标!!!(5)其他的方案,大同小异,都是根据需求,结合坐标,进行绘制。

下面我就具体讲下第三种

1、声明map以及polylineLayer(前面是地图,后面是画线),点位的声明,我就不做粘贴的,会一点都应该会撒点

<div class="echarts_heating" id="map"></div> //html

var map = new TMap.Map(document.getElementById("map"), {
    zoom: 11, //设置地图缩放级别
    center: center, //设置地图中心点坐标
    mapStyleId: "style1", //个性化样式默认style
    disableDefaultUI: true,
    showControl: false,
    baseMap: {
      type: "vector",
      features: ["base", "building3d", "point"], // 隐藏矢量文字可根据需求去配置
      
    },
    // mapStyleId: "style1", //设置样式ID,本例中的key绑定的style1为经典地图样式
    //(若使用未绑定的样式或无效ID,则会提示错误,并用地图默认样式显示)
  });

画线polylineLayer的声明以及线段的风格

  
var polylineLayer = new TMap.MultiPolyline({
    map, // 绘制到目标地图
    // 折线样式定义
    styles: {
      style_blue: new TMap.PolylineStyle({
        color: "#F15E59", // 线填充色
        width: 3, // 折线宽度
        lineCap: "round", // 线端头方式
      }),
      style_dash: new TMap.PolylineStyle({
        color: "#F15E59", // 线填充色
        width: 3, // 折线宽度
        lineCap: "butt", // 线端头方式
        dashArray: [6, 5], // 虚线展示方式
      }),
    },
    geometries: [],
  });

在vue的methods中

 //arr是点位坐标,[起点,终点] index,indexli,是为了不同的id所循环出来的,方便不同的命名,可取消
computeHeading(arr, index, indexli) {
  // 根据computeDistance去查询两点之前的距离
  let computeDistance = TMap.geometry.computeDistance(arr);
  // 查询两点之前的距离,如果距离过短,不进行任何处理
  if (computeDistance > 1500) {
    let computeHeading = TMap.geometry.computeHeading(arr[0], arr[1]);
    // 根据computeHeading,获取当前点位的的角度

    let du; //这个变量只是为了不让箭头的顶端和icon重叠而声明的反向的角度
    if (computeHeading > 0) {
      du = computeHeading - 180;
      // 因为地图的坐标系中只有【180,-180】所以进行逆时针转换
    } else {
      du = computeHeading + 180;
    }
    // path0 就是根据computeDestination,反向拿到的新的箭头顶点的坐标
    // 其中200,是icon与顶点的距离,可调整
    let path0 = TMap.geometry.computeDestination(arr[1], du, 200);
    // top1,top2,是画箭头的角度获取,
    // 因为地图的坐标系中只有【180,-180】所以进行逆时针转换
    // 我这边取得是偏移40度, 140,220,可调整
    let top1 = this.computeRotaion(computeHeading + 140);
    let top2 = this.computeRotaion(computeHeading + 220);
    // path1,path2是根据箭头的坐标,预计画的线段长度、以及角度,去获取箭头两边的点位坐标
    let path1 = TMap.geometry.computeDestination(path0, top1, 1200);
    let path2 = TMap.geometry.computeDestination(path0, top2, 1200);
    // console.log("path1", path1);
    // 根据获得到箭头的三点左边,进行绘制,这边也可以绘制覆盖性多边形 index,indexli,可修改,可取消,只要是不同的id即可
    this.polylineLayer.add({
      styleId: "style_blue",
      id: "pl1_" + index + "_" + indexli,
      paths: [path0, path1],
    });
    this.polylineLayer.add({
      styleId: "style_blue",
      id: "pl2_" + index + "_" + indexli,
      paths: [path0, path2],
    });
    // 根据不同长度,做不同的方案,根据长度在10000米以上的,我这边做中间的箭头,原理同上//
    if (computeDistance > 10000) {
      // 先拿到中间的点位坐标
      let pathzhong = TMap.geometry.computeDestination(
        arr[1],
        du,
        computeDistance / 2
      );
      // path3,path4,是中间箭头两边点位坐标,
      let path3 = TMap.geometry.computeDestination(pathzhong, top1, 1200);
      let path4 = TMap.geometry.computeDestination(pathzhong, top2, 1200);
      // 在根据三点坐标,进行画线,作出箭头 index,indexli,可修改,可取消,只要是不同的id即可
      this.polylineLayer.add({
        styleId: "style_blue",
        id: "pl3_" + index + "_" + indexli,
        paths: [pathzhong, path3],
      });
      this.polylineLayer.add({
        styleId: "style_blue",
        id: "pl4_" + index + "_" + indexli,
        paths: [pathzhong, path4],
      });
    }
  }
},
// 由于地图坐标的范围【180,-180】所以进行转化
computeRotaion(heading) {
  let rotation;
  if (heading > 180) {
    rotation = heading - 360;
  } else {
    rotation = heading;
  }
  return rotation;
}

注释中有完整的解释,需要耐心去看,也可以根据自身的情况去修改。我这里没有进行封装,但是可以正常的使用,如果你需要多组件调用,,需要自己去封装搞下,我就不在这把我需求封装的拿出来了,毕竟需求不同

总结:

希望多提意见,有更好的建议,可以留言,虚心学习!

卑微的小刘!