首页 前端知识 VUE引入高德地图实现驾车轨迹显示(简易版)

VUE引入高德地图实现驾车轨迹显示(简易版)

2024-05-10 22:05:34 前端知识 前端哥 102 574 我要收藏

1. 首先需要在高德地图注册对应的服务,注意绑定服务一定要是`web端`,如下图,我们会拥有对应的key值和安全密钥。

2. npm安装Loader

npm i @amap/amap-jsapi-loader --save

3. 创建一个地图容器组件,设置key和安全密钥

初始化时先设置安全密钥

window._AMapSecurityConfig = {
    securityJsCode: "xxxxxxxxxxxxxxxxxxxx",
};

 然后初始化地图,定义需要用到的插件

initAMap() {
      let that = this;
      AMapLoader.load({
        key: "xxxxxxxxxxxxxxxxxxxxxxxxxx", // 申请好的Web端开发者Key,首次调用 load 时必填
        version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
        plugins: [
          "AMap.ToolBar",
          "AMap.Scale",
          "AMap.HawkEye",
          "AMap.MapType",
          "AMap.Geolocation",
          "AMap.ControlBar",
          "AMap.MoveAnimation",
          "AMap.Driving",
          "AMap.Geocoder",
        ], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
      })
        .then((AMap) => {
          that.map = new AMap.Map("container", {
            // 设置地图容器id
            viewMode: "3D", // 是否为3D地图模式
            zooms: [5,14], // 初始化地图级别
            center: [116.397428, 39.90923], // 初始化地图中心点位置
            pitch: 45,
          });
          that.addMarker();
          window.calcDriving = () => {
            that.calcDriving();
          };
        })
        .catch((e) => {
          console.log(e);
        });
    }

 然后我们打上初始进入时当前车辆的点位进行信息展示

addMarker() {
      this.removeRouteLine();
      let that = this;
      this.mapStatus = 0;
      // 创建 AMap.Icon 实例:
      var icon = new AMap.Icon({
        size: new AMap.Size(20, 20), // 图标尺寸
        image: require("@/assets/mapMarker.png"), // Icon的图像
        imageSize: new AMap.Size(20, 20), // 根据所设置的大小拉伸或压缩图片
      });
      this.marker = new AMap.Marker({
        icon: icon,
        position: this.lntlat[0],
        offset: new AMap.Pixel(-10, -10),
      });
      this.map.add(this.marker);
      this.map.setFitView();

      // infowidnow 的 innerHTML
      var infoWindowContent = `
      <div class="map-info">
        <div class="info-item">
          <span>车牌号:</span>
          <span>${this.carInfo.label || "--"}</span>
        </div>
        <div class="info-item">
          <span>车队:</span>
          <span>${this.carInfo.parentLabel || "--"}</span>
        </div>
        <div class="info-item">
          <span>车主:</span>
          <span>${this.carInfo.driver || "--"}</span>
        </div>
        <div class="line"></div>
        <div class="button" onclick="calcDriving()">查看车辆轨迹 ></div>
      </div>
      `;

      // 创建一个自定义内容的 infowindow 实例
      var infoWindow = new AMap.InfoWindow({
        position: this.lntlat[0],
        offset: new AMap.Pixel(0, -10),
        content: infoWindowContent,
      });
      infoWindow.open(that.map);
      this.marker.on("click", function () {
        infoWindow.open(that.map);
      });
      this.map.setFitView(null, false);
    },

 我们每次进入或者切换车辆时,防止信息重叠展示,都是进行点位或者线路的清除

removeMarker() {
    this.marker && this.map.remove(this.marker);
},
removeRouteLine() {
    this.startMarker && this.map.remove(this.startMarker);
    this.endMarker && this.map.remove(this.endMarker);
    this.routeLine && this.map.remove(this.routeLine);
},

当我们要进行车辆轨迹查看时,实际逻辑是传递了两个经纬度点位的数据,我们使用高德api自带的轨迹规划可以实现线路图的展示。

calcDriving() {
      this.removeMarker();
      this.map.clearInfoWindow();
      this.mapStatus = 1;
      this.regeoCode(this.carInfo.rotes.startLocation, 0);
      this.regeoCode(this.carInfo.rotes.endLocation, 1);
      let that = this;
      var drivingOption = {
        policy: AMap.DrivingPolicy.LEAST_TIME, // 其它policy参数请参考 https://lbs.amap.com/api/javascript-api/reference/route-search#m_DrivingPolicy
        ferry: 1, // 是否可以使用轮渡
        province: "鲁", // 车牌省份的汉字缩写
      };

      // 构造路线导航类
      var driving = new AMap.Driving(drivingOption);

      // 根据起终点经纬度规划驾车导航路线
      driving.search(this.lntlat[0], this.lntlat[1], function (status, result) {
        // result即是对应的驾车导航信息,相关数据结构文档请参考 https://lbs.amap.com/api/javascript-api/reference/route-search#m_DrivingResult
        if (status === "complete") {
          if (result.routes && result.routes.length) {
            // 绘制第一条路线,也可以按需求绘制其它几条路线
            that.drawRoute(result.routes[0]);
            // log.success('绘制驾车路线完成')
          }
        } else {
          // log.error('获取驾车数据失败:' + result)
        }
      });
    },
    drawRoute(route) {
      var path = this.parseRouteToPath(route);
      var icon = new AMap.Icon({
        size: new AMap.Size(20, 20), // 图标尺寸
        image: require("@/assets/mapMarker.png"), // Icon的图像
        imageSize: new AMap.Size(20, 20), // 根据所设置的大小拉伸或压缩图片
      });
      this.startMarker = new AMap.Marker({
        position: path[0],
        icon: icon,
        map: this.map,
        offset: new AMap.Pixel(-10, -10),
      });

      this.endMarker = new AMap.Marker({
        position: path[path.length - 1],
        icon: icon,
        map: this.map,
        offset: new AMap.Pixel(-10, -10),
      });

      this.routeLine = new AMap.Polyline({
        path: path,
        isOutline: true,
        outlineColor: "#ffeeee",
        borderWeight: 2,
        strokeWeight: 5,
        strokeOpacity: 0.9,
        strokeColor: "#0091ff",
        lineJoin: "round",
      });

      this.map.add(this.routeLine);

      // 调整视野达到最佳显示区域
      this.map.setFitView([this.startMarker, this.endMarker, this.routeLine]);
    },
    parseRouteToPath(route) {
      var path = [];

      for (var i = 0, l = route.steps.length; i < l; i++) {
        var step = route.steps[i];

        for (var j = 0, n = step.path.length; j < n; j++) {
          path.push(step.path[j]);
        }
      }

      return path;
    },

 其中,左上角展示了24小时车辆运行情况的地址,这需要我们使用高德提供的逆地理定位获取地址的信息。

regeoCode(lnglat, id) {
      let that = this;
      var geocoder = new AMap.Geocoder({
        // city: "010", //城市设为北京,默认:“全国”
        radius: 1000, //范围,默认:500
      });
      geocoder.getAddress(lnglat, function (status, result) {
        if (status === "complete" && result.regeocode) {
          var address = result.regeocode.formattedAddress;
          that.activities[id].content = address;
        } else {
          console.log("根据经纬度查询地址失败");
        }
      });
    },

需要注意的是,由于我们的初始化地图是写在methods方法里的,所以调用起来有一定的问题 ,比如车辆轨迹的函数我们绑定在了div元素里,但是如果我们不进行特殊处理,只在methods里定义calcDriving()函数,调用会报AMap的错误;

这还因为我们外层是没有定义过AMap的,只需要在初始化时增加这样一部就可以解决这个问题。

window.calcDriving = () => {

        that.calcDriving();

};

最后,附上源码:

1.MapContainer.vue定义地图组件

<template>
  <div class="map-box">
    <div class="carInfoBox" v-if="mapStatus == 1">
      <div class="carInfo">
        <span>车牌号:</span>
        <span class="carNo">鲁A00004</span>
      </div>
      <p class="title">24小时车辆运行情况:</p>
      <div class="rote-box">
        <el-timeline :reverse="true">
          <el-timeline-item
            v-for="(activity, index) in activities"
            :key="index"
            icon="el-icon-coordinate"
            type="primary"
            :color="activity.color"
            size="large"
            :timestamp="activity.timestamp"
          >
            {{ activity.content }}
          </el-timeline-item>
        </el-timeline>
      </div>
    </div>
    <div class="returnBtn" @click="addMarker" v-if="mapStatus == 1">返回</div>
    <div id="container"></div>
  </div>
</template>
<script>
import AMapLoader from "@amap/amap-jsapi-loader";
import moment from "moment";
export default {
  name: "map-view",
  props: ["lntlat", "carInfo"],
  data() {
    return {
      map: "",
      marker: null,
      routeLine: null,
      startMarker: null,
      endMarker: null,
      activities: [
        {
          content: "山东省济南市市中区十六里河街道漫山香墅宸麓6号楼",
          timestamp: "2018-04-12 20:46",
        },
        {
          content: "山东省烟台市莱山区解甲庄街道钟家洼",
          timestamp: "2018-04-03 20:46",
        },
      ],
      mapStatus: 0,
    };
  },
  watch: {
    lntlat: {
      handler: function (newVal, oldVal) {
        this.$nextTick(() => {
          if (this.map) {
            this.removeMarker();
            this.addMarker();
          }
        });
      },
      deep: true,
    },
    carInfo() {
      this.activities[0].timestamp = moment().format("YYYY-MM-DD HH:mm");
      this.activities[1].timestamp =
        moment().subtract(1, "day").format("YYYY-MM-DD HH:mm");
    },
  },
  mounted() {
    window._AMapSecurityConfig = {
      securityJsCode: "xxxxxxxxxxxxxxxxxxxx",//安全秘钥
    };
    this.initAMap();
  },
  unmounted() {
    this.map.destroy();
  },
  methods: {
    initAMap() {
      let that = this;
      AMapLoader.load({
        key: "xxxxxxxxxxxxxxxxxxxxxxx", // 申请好的Web端开发者Key,首次调用 load 时必填
        version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
        plugins: [
          "AMap.ToolBar",
          "AMap.Scale",
          "AMap.HawkEye",
          "AMap.MapType",
          "AMap.Geolocation",
          "AMap.ControlBar",
          "AMap.MoveAnimation",
          "AMap.Driving",
          "AMap.Geocoder",
        ], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
      })
        .then((AMap) => {
          that.map = new AMap.Map("container", {
            // 设置地图容器id
            viewMode: "3D", // 是否为3D地图模式
            zooms: [5,14], // 初始化地图级别
            center: [116.397428, 39.90923], // 初始化地图中心点位置
            pitch: 45,
          });
          that.addMarker();
          window.calcDriving = () => {
            that.calcDriving();
          };
        })
        .catch((e) => {
          console.log(e);
        });
    },
    removeMarker() {
      this.marker && this.map.remove(this.marker);
    },
    removeRouteLine() {
      this.startMarker && this.map.remove(this.startMarker);
      this.endMarker && this.map.remove(this.endMarker);
      this.routeLine && this.map.remove(this.routeLine);
    },
    addMarker() {
      this.removeRouteLine();
      let that = this;
      this.mapStatus = 0;
      // 创建 AMap.Icon 实例:
      var icon = new AMap.Icon({
        size: new AMap.Size(20, 20), // 图标尺寸
        image: require("@/assets/mapMarker.png"), // Icon的图像
        imageSize: new AMap.Size(20, 20), // 根据所设置的大小拉伸或压缩图片
      });
      this.marker = new AMap.Marker({
        icon: icon,
        position: this.lntlat[0],
        offset: new AMap.Pixel(-10, -10),
      });
      this.map.add(this.marker);
      this.map.setFitView();

      // infowidnow 的 innerHTML
      var infoWindowContent = `
      <div class="map-info">
        <div class="info-item">
          <span>车牌号:</span>
          <span>${this.carInfo.label || "--"}</span>
        </div>
        <div class="info-item">
          <span>车队:</span>
          <span>${this.carInfo.parentLabel || "--"}</span>
        </div>
        <div class="info-item">
          <span>车主:</span>
          <span>${this.carInfo.driver || "--"}</span>
        </div>
        <div class="line"></div>
        <div class="button" onclick="calcDriving()">查看车辆轨迹 ></div>
      </div>
      `;

      // 创建一个自定义内容的 infowindow 实例
      var infoWindow = new AMap.InfoWindow({
        position: this.lntlat[0],
        offset: new AMap.Pixel(0, -10),
        content: infoWindowContent,
      });
      infoWindow.open(that.map);
      this.marker.on("click", function () {
        infoWindow.open(that.map);
      });
      this.map.setFitView(null, false);
    },

    regeoCode(lnglat, id) {
      let that = this;
      var geocoder = new AMap.Geocoder({
        // city: "010", //城市设为北京,默认:“全国”
        radius: 1000, //范围,默认:500
      });
      geocoder.getAddress(lnglat, function (status, result) {
        if (status === "complete" && result.regeocode) {
          var address = result.regeocode.formattedAddress;
          that.activities[id].content = address;
        } else {
          console.log("根据经纬度查询地址失败");
        }
      });
    },
    calcDriving() {
      this.removeMarker();
      this.map.clearInfoWindow();
      this.mapStatus = 1;
      this.regeoCode(this.carInfo.rotes.startLocation, 0);
      this.regeoCode(this.carInfo.rotes.endLocation, 1);
      let that = this;
      var drivingOption = {
        policy: AMap.DrivingPolicy.LEAST_TIME, // 其它policy参数请参考 https://lbs.amap.com/api/javascript-api/reference/route-search#m_DrivingPolicy
        ferry: 1, // 是否可以使用轮渡
        province: "鲁", // 车牌省份的汉字缩写
      };

      // 构造路线导航类
      var driving = new AMap.Driving(drivingOption);

      // 根据起终点经纬度规划驾车导航路线
      driving.search(this.lntlat[0], this.lntlat[1], function (status, result) {
        // result即是对应的驾车导航信息,相关数据结构文档请参考 https://lbs.amap.com/api/javascript-api/reference/route-search#m_DrivingResult
        if (status === "complete") {
          if (result.routes && result.routes.length) {
            // 绘制第一条路线,也可以按需求绘制其它几条路线
            that.drawRoute(result.routes[0]);
            // log.success('绘制驾车路线完成')
          }
        } else {
          // log.error('获取驾车数据失败:' + result)
        }
      });
    },
    drawRoute(route) {
      var path = this.parseRouteToPath(route);
      var icon = new AMap.Icon({
        size: new AMap.Size(20, 20), // 图标尺寸
        image: require("@/assets/mapMarker.png"), // Icon的图像
        imageSize: new AMap.Size(20, 20), // 根据所设置的大小拉伸或压缩图片
      });
      this.startMarker = new AMap.Marker({
        position: path[0],
        icon: icon,
        map: this.map,
        offset: new AMap.Pixel(-10, -10),
      });

      this.endMarker = new AMap.Marker({
        position: path[path.length - 1],
        icon: icon,
        map: this.map,
        offset: new AMap.Pixel(-10, -10),
      });

      this.routeLine = new AMap.Polyline({
        path: path,
        isOutline: true,
        outlineColor: "#ffeeee",
        borderWeight: 2,
        strokeWeight: 5,
        strokeOpacity: 0.9,
        strokeColor: "#0091ff",
        lineJoin: "round",
      });

      this.map.add(this.routeLine);

      // 调整视野达到最佳显示区域
      this.map.setFitView([this.startMarker, this.endMarker, this.routeLine]);
    },
    parseRouteToPath(route) {
      var path = [];

      for (var i = 0, l = route.steps.length; i < l; i++) {
        var step = route.steps[i];

        for (var j = 0, n = step.path.length; j < n; j++) {
          path.push(step.path[j]);
        }
      }

      return path;
    },
  },
};
</script>
<style lang="scss" scoped>
#container {
  width: 100%;
  height: 88vh;
}
.map-box {
  position: relative;
  .returnBtn {
    position: absolute;
    z-index: 999;
    right: 20px;
    top: 20px;
    padding: 10px 30px;
    border: 1px solid #3c9efb;
    background: #1e4bc3;
    color: #f2f2f2;
    cursor: pointer;
  }
  .carInfoBox {
    position: absolute;
    z-index: 999;
    left: 20px;
    top: 20px;
    background: #283997cf;
    color: #fff;
    padding: 20px;
    font-size: 14px;
    .carInfo {
      margin-bottom: 10px;
      font-size: 14px;
    }
    .carNo {
      margin-left: 20px;
    }
    .title {
      margin-bottom: 10px;
    }
    .rote-box {
      padding: 10px;
    }
  }
}
/deep/ {
  .el-timeline-item__node--large {
    left: -5px;
    width: 20px;
    height: 20px;
  }
  .el-timeline-item__wrapper {
    padding-bottom: 20px;
  }
  .el-timeline-item__content {
    color: #fff;
  }
  .el-timeline-item__timestamp {
    color: #bec3cd;
  }
  .el-timeline-item {
    padding-bottom: 0;
  }
  .el-timeline-item:nth-child(2) {
    .el-timeline-item__wrapper {
      padding-bottom: 0px;
    }
  }
  .amap-info-content {
    background: #283997cf;
  }
  .bottom-center .amap-info-sharp {
    border-color: #283997cf;
    border-left: 8px solid transparent;
    border-right: 8px solid transparent;
  }
  .map-info {
    font-size: 14px;
    // padding: 10px 16px 8px;
    // background: #283997cf;
    color: bisque;
  }
  .info-item {
    width: 145px;
    display: flex;
    span {
      display: inline-block;
      width: 50%;
      padding: 4px 0;
    }
  }
  .line {
    width: 100%;
    height: 1px;
    background: #6ca3da;
  }
  .button {
    text-align: center;
    padding: 6px 0;
    cursor: pointer;
  }
}
</style>

2.carMap.vue调用地图组件进行渲染

<template>
  <div class="carMap">
    <div class="carMapRight">
      <Mapview
        ref="carMap"
        :lntlat="checkObj.lnglnt"
        :carInfo="checkObj"
      ></Mapview>
    </div>
  </div>
</template>

<script>
import Mapview from "@/components/MapContainer.vue";
export default {
  name: "carMap",
  components: {
    Mapview,
  },
  props: {},
  data() {
    return {
      checkObj: {
            id: "1-2",
            label: "鲁A00002",
            parentId: 1,
            parentLabel: "第一车队",
            driver: "王勇",
            type: 2,
            rotes: {
              startTime: "2024-01-16 10:44",
              endTime: "2023-01-17 10:44",
              startLocation: [118.46999, 37.520299],
              endLocation: [117.131897, 36.162652],
            },
        },
    };
  },
  watch:{},
  mounted() {},
  computed: {},
  methods: {},
  destroyed() {},
};
</script>
<style lang="scss" scoped>
* {
  margin: 0;
  padding: 0;
}

html,
body {
  width: 100%;
  height: 100%;
}

.carMap {
  padding: 20px;
  width: 100%;
  box-sizing: border-box;
  display: flex;
}

.carMapRight {
  width: 80%;
  height: 88vh;
}
</style>

转载请注明出处或者链接地址:https://www.qianduange.cn//article/7983.html
标签
评论
发布的文章

HTML5(H5)中的Web Workers

2024-05-19 09:05:52

HTML5

2024-02-27 11:02:15

HTML5 <option> 标签

2024-05-19 09:05:51

@JsonProperty 注解详解

2024-05-19 09:05:27

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!