百度、高德地图中心点设置和路径规划(当有路径规划时设置为视野中心)

百度地图、高德地图中心点设置和路径规划

a.前期准备

引入bmap.js文件

  1. 获取js文件,浏览器输入url:
http://api.map.baidu.com/api?v=3.0&ak=你的ak

在这里插入图片描述

  1. 对应输入百度ak,并复制标黄的部分在浏览器打开,将其中的内容复制到bmap.js文件中
    在这里插入图片描述
    在这里插入图片描述

b.地图组件主要代码

  1. index.vue文件
    在这里插入图片描述
<template>
  <div :id="id" class="map-container"></div>
</template>

<script>
import { getDrivingRoute, getCityPosition, getBdDrivingRoute, getBdCityPosition } from "./api/index";
import { mapGetters } from "vuex";

export default {
  name: "ZitMap",
  props: {
    id: {
      type: String,
      default: "map-container",
    },
    amapServerURL: String,
    bmapServerURL: String,
    amapKey: String,
    bmapBsKey: String,
    bmapKey: String,
    amapServiceKey: String,
    bmapServiceKey: String,
    secureKey: String,
    startPos: {
      type: Array,
      default: () => [],
    },
    endPos: {
      type: Array,
      default: () => [],
    },
  },
  data() {
    return {
      map: null,
      polyline: null,
      ambulMarker: null,
      hospitalMarker: null,
      timer: null,
      ambulIcon: require("./assets/img/ambul2.png"),
      hospitalIcon: require("./assets/img/hospital2.gif"),
    };
  },
  computed: {
    ...mapGetters("settings", ["webConfig"]),
  },
  watch: {
    startPos() {
      console.log('起点变化了');
      this.clearMap();
      if(this.webConfig.MAP_USE == 0){
        console.log(this.startPos,this.endPos,'起点终点高德经纬度111');
        this.createAMapMarkers();
        this.drawAMapRoute();
      }else if(this.webConfig.MAP_USE == 1){
        console.log(this.startPos,this.endPos,'起点终点百度经纬度111');
        this.createBMapMarkers();
        this.drawBMapRoute();
      }
      // this.drawRoute();
    },
  },
  mounted() {
    this.loadMapJS();
  },
  beforeDestroy() {
    this.destroyMap();
  },
  methods: {
    // 动态加载地图 JS 文件
    loadMapJS() {
      if (this.webConfig.MAP_USE == 0) {
        this.loadAMapJS();
      } else if (this.webConfig.MAP_USE == 1) {
        this.loadBMapJS();
      }
    },

    // 加载高德地图 JS 文件
    loadAMapJS() {
      window.amapServerURL = this.amapServerURL.replace(/(https?:\/\/)/, "");
      window.amapKey = this.amapKey;
      window._AMapSecurityConfig = {
        securityJsCode: this.secureKey,
      };
      this.loadJS(() => {
        this.initAMap();
      }, "/js/amap/amap.js?v=" + Date.now());
    },

    // 加载百度地图 JS 文件
    loadBMapJS() {
      window.bmapKey = this.bmapKey; //浏览器端密钥,用来初始化地图
      window.bmapBsKey = this.bmapBsKey; // 服务端密钥,用来获取中心点和获取路径规划
      this.loadJS(() => {
        this.initBMap();
      }, "/js/bmap/bmap.js?v=" + Date.now());
    },

    // 初始化高德地图,设置传入的城市为地图中心点(如果后面有路径规划,则设置路径规划为地图中心点)
    async initAMap() {
      try {
        const cityData = await getCityPosition(this.webConfig.CITY, this.amapServiceKey);
        const location = cityData.geocodes[0].location.split(",");

        this.map = new window.AMap.Map(this.id, {
          zoom: 10,
        });

        if (location) {
          this.map.setZoomAndCenter(10, location);
        }

        this.createAMapMarkers();
        this.drawAMapRoute();
      } catch (error) {
        console.error("高德地图初始化失败:", error);
      }
    },

    // 初始化百度地图,设置传入的城市为地图中心点(如果后面有路径规划,则设置路径规划为地图中心点)
    async initBMap() {
      try {
        const cityData = await getBdCityPosition(this.webConfig.CITY, this.bmapKey);
        const location = cityData.result.location;

        // this.map = new window.Map(this.id);
        this.map = new BMapGL.Map(this.id, {
          zoom: 10,
        });
        this.map.centerAndZoom(new window.BMapGL.Point(location.lng, location.lat), 10);
        this.map.enableScrollWheelZoom(true)
        this.createBMapMarkers();
        this.drawBMapRoute();
      } catch (error) {
        console.error("百度地图初始化失败:", error);
      }
    },

    // 创建高德地图标记
    createAMapMarkers() {
      this.ambulMarker = this.createAMapMarker({
        width: 40,
        height: 40,
        lng: this.startPos[0] || 116.481028,
        lat: this.startPos[1] || 39.989643,
        image: this.ambulIcon,
      });

      this.hospitalMarker = this.createAMapMarker({
        width: 40,
        height: 40,
        lng: this.endPos[0] || 116.465302,
        lat: this.endPos[1] || 40.004717,
        image: this.hospitalIcon,
      });
    },

    // 创建百度地图标记
    createBMapMarkers() {
      console.log(this.endPos,this.startPos,'百度终点起点坐标');

      this.ambulMarker = this.createBMapMarker({
        width: 40,
        height: 40,
        lng: this.startPos[0] || 116.481028,
        lat: this.startPos[1] || 39.989643,
        image: this.ambulIcon,
      });

      this.hospitalMarker = this.createBMapMarker({
        width: 40,
        height: 40,
        lng: this.endPos[0] || 116.465302,
        lat: this.endPos[1] || 40.004717,
        image: this.hospitalIcon,
      });
    },

    // 绘制路线
    drawRoute() {
      if (this.webConfig.MAP_USE == 0) {
        this.drawAMapRoute();
      } else if (this.webConfig.MAP_USE == 1) {
        this.drawBMapRoute();
      }
    },

    // 绘制高德地图路线
    async drawAMapRoute() {
      if (!this.map || this.startPos.length < 2 || this.endPos.length < 2) {
        return;
      }

      try {
        const res = await getDrivingRoute(
          this.startPos.join(","),
          this.endPos.join(","),
          this.amapServiceKey
        );

        const {
          route: { paths },
        } = res;
        const { distance, duration, steps } = paths[0];
        this.$emit('complete',{distance,duration});
        const pathList = steps
          .map(({ polyline }) => polyline.split(";"))
          .flatMap((step) => step.map((item) => new window.AMap.LngLat(...item.split(","))));

        if (this.polyline) {
          this.map.remove(this.polyline);
        }

        this.polyline = new window.AMap.Polyline({
          path: pathList,
          borderWeight: 2,
          strokeColor: "green",
          lineJoin: "round",
        });

        this.ambulMarker.setPosition(new window.AMap.LngLat(...this.startPos));
        this.hospitalMarker.setPosition(new window.AMap.LngLat(...this.endPos));

        this.map.add([this.polyline, this.ambulMarker, this.hospitalMarker]);
        // 路径规划设置为视野中心
        this.map.setFitView([this.polyline], true, [5, 5, 5, 5], 17);
        this.$emit("done", distance, duration);
      } catch (error) {
        console.error("高德地图路线绘制失败:", error);
      }
    },

    // 绘制百度地图路线
    async drawBMapRoute() {
      if (!this.map || this.startPos.length < 2 || this.endPos.length < 2) {
        return;
      }

      try {
      const startJWD = [this.startPos[1],this.startPos[0]];
      const endJWD = [this.endPos[1],this.endPos[0]];
        const res = await getBdDrivingRoute(
          startJWD.join(","),
          endJWD.join(","),
          this.bmapKey
        );

        const { result: { routes } } = res;
        const { distance, duration, steps } = routes[0];
        this.$emit('complete',{distance,duration});
        const pathList = steps
          .map(({ path }) => path.split(";"))
          .flatMap((step) => step.map((item) => new window.BMapGL.Point(...item.split(","))));

        if (this.polyline) {
          this.map.removeOverlay(this.polyline);
        }
        console.log(pathList)
        this.polyline = new window.BMapGL.Polyline(pathList, {
          strokeColor: "green",
          strokeWeight: 2,
          strokeOpacity: 1,
        });

        // this.ambulMarker.setPosition(new window.BMapGL.Point(...this.startPos));
        // this.hospitalMarker.setPosition(new window.BMapGL.Point(...this.endPos));
        
        this.map.addOverlay(this.polyline);
        this.map.addOverlay(this.ambulMarker);
        this.map.addOverlay(this.hospitalMarker);
        const polyCenter = [new BMapGL.Point(this.startPos[0],this.startPos[1]),new BMapGL.Point(this.endPos[0],this.endPos[1])];
        // 路径规划设置为视野中心
        this.map.setViewport(polyCenter,{
          enableAnimation: true,
          margins: [10, 10, 10, 10]
          });
        this.$emit("done", distance, duration);
      } catch (error) {
        console.error("百度地图路线绘制失败:", error);
      }
    },

    // 创建高德地图标记
    createAMapMarker({ width = 40, height = 40, lng = "", lat = "", image, label = "" }) {
      const icon = new window.AMap.Icon({
        size: new window.AMap.Size(width, height),
        image,
        imageSize: new window.AMap.Size(width, height),
      });

      const marker = new window.AMap.Marker({
        position: new window.AMap.LngLat(lng, lat),
        offset: new window.AMap.Pixel(-width / 2, -height / 2),
        icon,
        title: "",
      });

      if (label) {
        marker.setLabel({
          offset: new window.AMap.Pixel(0, -15),
          content: `<div class="amap-marker-label">${label}</div>`,
        });
      }

      return marker;
    },

    // 创建百度地图标记
    createBMapMarker({ width = 40, height = 40, lng = "", lat = "", image, label = "" }) {
      const icon = new window.BMapGL.Icon(image, new window.BMapGL.Size(width, height));
      const pt = new window.BMapGL.Point(lng, lat)
      const marker = new window.BMapGL.Marker(pt, { icon });

      if (label) {
        const labelOpts = {
          offset: new window.BMapGL.Size(0, -15),
          content: `<div class="bmap-marker-label">${label}</div>`,
        };
        marker.setLabel(labelOpts);
      }

      return marker;
    },

    // 清理地图
    clearMap() {
      if (this.map) {
        if (this.webConfig.MAP_USE == 0) {
          this.polyline && this.map.remove(this.polyline);
          this.ambulMarker && this.map.remove(this.ambulMarker);
          this.hospitalMarker && this.map.remove(this.hospitalMarker);
          this.map.clearMap();
        } else if (this.webConfig.MAP_USE == 1) {
          this.polyline && this.map.removeOverlay(this.polyline);
          this.ambulMarker && this.map.removeOverlay(this.ambulMarker);
          this.hospitalMarker && this.map.removeOverlay(this.hospitalMarker);
          this.map.clearOverlays();
        }
      }
    },

    // 销毁地图
    destroyMap() {
      if (this.timer) {
        clearInterval(this.timer);
        this.timer = null;
      }
      if (this.map) {
        this.map.destroy();
        this.map = null;
      }
    },

    // 动态加载 JS 文件
    loadJS(callback, url) {
      let script = document.createElement("script");
      script.type = "text/javascript";
      script.readyState
        ? (script.onreadystatechange = (e) => {
          const { readyState } = script;
          if (readyState == "loaded" || readyState == "complete") {
            callback && callback();
            script.onreadystatechange = null;
          }
        })
        : (script.onload = (e) => {
          callback && callback();
        });

      script.onerror = (e) => {
        this.mapError = true;
        this.$message({
          showClose: true,
          message: "地图加载失败!",
          type: "error",
          duration: 5000,
        });
        console.log(e);
      };
      script.src = url;
      document.body.appendChild(script);
    },
  },
};
</script>

<style scoped>
.map-container {
  width: 100%;
  height: 100%;
  flex: 1;
}
</style>
  1. api/index.js文件
import axios from "@network";

/**
 * 
 * @param {*} origin eg. 116.481028,39.989643
 * @param {*} destination eg. 116.465302,40.004717
 * @param {*} key eg. 336200d534d6e0303b0267cf1f11c5af
 * @returns 
 */
export const getDrivingRoute = (origin, destination, key) => {
  const url = `/PROXY_AMAP/direction/driving`;

  return axios.get(url, {
    params: {
      origin,
      destination,
      key,
      extensions: 'all',
      output: 'json',
    }
  });
}

export const getCityPosition = (address, key) => {
  const url = `/PROXY_AMAP/geocode/geo`;

  return axios.get(url, {
    params: {
      address,
      key,
      output: 'json',
    }
  });
}
// 百度
export const getBdDrivingRoute = (origin, destination, ak) => {
  const url = `/PROXY_BDMAP/direction/v2/driving`;

  return axios.get(url, {
    params: {
      origin,
      destination,
      ak
    }
  });
}

export const getBdCityPosition = (address, ak) => {
  const url = `/PROXY_BDMAP/geocoding/v3`;

  return axios.get(url, {
    params: {
      address,
      ak,
      output: 'json',
    }
  });
}

c.调用地图组件

<template>
  <div style="margin-top:50px">
    <el-collapse v-model="activeNames" class="collapse">
      <el-collapse-item name="1" class="collapse-item">
        <template slot="title">
          <div class="text-xl">实时定位</div>
        </template>
        <div class="container">
          <div class="show">
            <div class="distance-wrapper">
              <div class="distance">预估距离</div>
              <div class="distance-value">
                <span class="value">
                  {{ distance?distance:'未知' }}
                </span>
                <span class="unit">km</span>
              </div>
            </div>
            <div class="split"></div>
            <div class="duration-wrapper">
              <div class="duration">预计用时</div>
              <div class="duration-value">
                <span class="value">
                  {{ minutes?minutes:'未知' }}
                </span>
                <span class="unit"></span>
                <span class="value" style="margin-left: 10px">
                  {{ seconds?seconds:'未知' }}
                </span>
                <span class="unit"></span>
              </div>
            </div>
          </div>
          <div class="map" id="map-container">
            <zit-map
              :startPos="ambulPos"
              :endPos="hospitalPos"
              :amapServerURL="webConfig.serverURL"
              :bmapServerURL="webConfig.serverURL"
              :amapKey="webConfig.AMAP_KEY"
              :bmapKey="webConfig.DEFAULT_BDBSMAP_AK"
              :bmapBsKey="webConfig.DEFAULT_BDMAP_AK"
              :amapServiceKey="webConfig.AMAP_SERVICE_KEY"
              :secureKey="webConfig.SECUREKEY"
              @complete="getTimeAndDis"
            ></zit-map>
          </div>
        </div>
      </el-collapse-item>
    </el-collapse>
  </div>
</template>

<script>
import { mapGetters } from "vuex";
import { findTaskDetail } from "@api/warning-info";

export default {
  name: "RealTimeLocation",
  // props: {
  //   ambulOutInfo: {
  //     type: Array,
  //     required: true,
  //   },
  //   videoInfo: {
  //     type: Array,
  //     required: true,
  //   },
  // },
  components: {
    ZitMap,
    CommonVideo,
    HaikangVideo,
    HaikangVideoNew,
    TopBar,
  },
  data() {
    return {
      ambulOutInfo: {},
      videoInfo: [],
      activeNames: ["1", "2", "3"],
      ambulPos: [],
      hospitalPos: [],
      time:"",
      minutes:"",
      seconds:"",
      distance:""
    };
  },
  computed: {
    ...mapGetters("settings", ["webConfig", "serverConfig"]),
  mounted() {
    this.findTaskDetail('20250207010001000006');// 为了获取经纬度
  },
  methods: {
    getTimeAndDis({distance: dis, duration: dur}){
      this.minutes = this.formatMinute(dur);
      this.seconds = this.formatSecond(dur);
      this.distance = this.formatDistance(dis);
    },
    // 时间转换
    formatMinute(time){
      const minute = Math.floor(time / 60);
      return minute;
    },
    formatSecond(time){
      const second = Math.floor(time % 60);
      return second;
    },
    // 距离转换
    formatDistance(distance){
      return `${(distance / 1000).toFixed(1)}`;
    },
    async findTaskDetail(lsh) {
      const warnTaskDetail = await findTaskDetail({
        lsh,
      });
      this.ambulOutInfo = warnTaskDetail.lst_ambul_out;  // 获取经纬度,为空的话写死一个以供测试
      const ambuJd = this.ambulOutInfo[0].ccsjJd?this.ambulOutInfo[0].ccsjJd:118.796624;
      const ambuWd = this.ambulOutInfo[0].ccsjWd?this.ambulOutInfo[0].ccsjWd:32.059344;
      const hosJd = this.ambulOutInfo[0].ccsjJd?this.ambulOutInfo[0].ccsjJd:116.322056;
      const hosWd = this.ambulOutInfo[0].ccsjWd?this.ambulOutInfo[0].ccsjWd:39.89491;
      
      this.ambulPos = [ambuJd, ambuWd];
      this.hospitalPos = [hosJd,hosWd];
    },
};
</script>

<style lang="scss" scoped>
.show {
    position: absolute;
    display: flex;
    align-items: center;
    // top: 3px;
    background-color: #fff;
    z-index: 999;
    border-radius: 20px;
    width: 78%;
    height: 80px;
    left: 40%;
    transform: translate(-50%, 0);
    border-radius: 5px;
    background: linear-gradient(180deg, #ffeeee 0%, #f7bdbd 100%);
    box-sizing: border-box;
    box-shadow: rgba(60, 64, 67, 0.3) 0px 1px 2px 0px,
    rgba(60, 64, 67, 0.15) 0px 2px 6px 2px;

    .distance-wrapper,
    .time-wrapper,
    .duration-wrapper {
      flex: 1;
      height: 100%;
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
      line-height: 30px;
    }

    .distance {
      font-size: 16px;
      color: #833636;
      font-weight: bold;
    }

    .distance-value {
      font-size: 32px;
      color: #833636;
      font-weight: bold;
    }

    .value {
      margin-right: 10px;
      font-size: 45px;
      font-family: "led regular";
    }

    .unit {
      font-size: 16px;
      color: #833636;
      font-weight: bold;
    }

    .split {
      width: 0;
      height: 0;
      margin-right: -1px;
      border-left: 30px solid transparent;
      border-bottom: 80px solid #fc8080;
    }

    .split_own {
      width: 0;
      height: 0;
      margin-right: -1px;
      border-right: 30px solid transparent;
      border-top: 80px solid #fc8080;
    }

    .arrival {
      font-size: 16px;
      color: #000;
      font-weight: bold;
    }

    .arrival-value {
      font-size: 32px;
      color: #000;
      font-weight: bold;
    }

    .duration-wrapper {
      background-color: #fc8080;
      // border-radius: 5px;
      margin-right: -1px;
      border-bottom-left-radius: 0;

      .duration {
        font-size: 16px;
        color: #fff;
        font-weight: bold;
      }

      .duration-value {
        font-size: 32px;
        color: #fff;
        font-weight: bold;
      }

      // 单位
      .unit {
        font-size: 16px;
        color: #fff;
        font-weight: bold;
      }
    }
  }
.collapse {
  width: 100%;
  font-size: 28px;
  margin-top: 20px;

  .collapse-item {
    width: 100%;
  }

  .text-xl {
    font-size: 20px;
    font-weight: bold;
    color: #3891a0;
    margin-left: 15px;
  }
}

.container {
  display: flex;
  height: 620px;
  width: 98%;

  .map {
    width: 80%;
    // height: 738px;
    margin: 88px 0px 0px 12px;
  }
}
</style>

d.成果展示

  1. 百度地图
    在这里插入图片描述
  2. 高德地图
    在这里插入图片描述

需要注意的是,有时候坐标并不是直接可以使用的,需要进行坐标系的转换,这个后续有空再记录……

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值