vue3+openlayer+天地图api实现路径规划

html 

<!-- 路径展示 -->
    <div class="lujing-list" :style="{ left: lif }">
      <div class="bottomBg"></div>
      <div class="head">
        <headTitle title="路径展示" style="width: 80%"></headTitle>
        <el-button type="primary" @click="lxHide" circle
          style="width: 25px; height: 25px; border: 0; align-self: center">
          <ArrowLeftBold style="width: 1em; height: 1em" />
        </el-button>
      </div>
      <div class="show-area">
        <div class="luxian-title">转移路线:</div>
        <div v-for="(item, index) in routesTxtList" :key="index" class="lx-area">
          <p>{{ item }}</p>
          <p class="pxia" v-if="index != routesTxtList.length -1">↓</p>
        </div>
      </div>
    </div>

data 

	//以下是轨迹
const trackLayer = ref();
const passCoordinates = ref([]);
//  记录开始动画的时间
const startTime = ref(0);
// 轨迹分割的颗粒度,数值越小分的越细
const particle = 20;
// 轨迹动画的速度,数值越大位移越快
const speed = 5;
let routesTxtList = ref([]) //路径文本列表
let lif = ref('-100%');//左侧面板距离

js 

//画路线
function drawLuxian(start, end){
  removeTrak()
  axios.get('https://api.tianditu.gov.cn/drive?postStr={orig:"' + start + '",dest:"' + end + '",style:"0"}&type=search&tk=46f132f7078fa807641aa8644dc60eb1', {})
  .then(res=>{
    if (res?.status == 200){
      let parser = new DOMParser();
      let xmlDoc = parser.parseFromString(res.data, "application/xml");
      let routelatlon = xmlDoc.getElementsByTagName("routelatlon")[0].textContent
      routelatlon = routelatlon.substring(0, routelatlon.length - 1);
      let routes = xmlDoc.getElementsByTagName("routes")[0].getElementsByTagName("item")
      routesTxtList.value = []
      for (let i = 0; i < routes.length; i++) {
        let strguide = routes[i].getElementsByTagName("strguide")[0];
        let text = strguide.textContent;  // 获取文本内容
        routesTxtList.value.push(text)
      }
      let list = routelatlon.split(";").map(e=>{
        return [parseFloat(e.split(",")[0]), parseFloat(e.split(",")[1])]
      })
      addTrack(list);
      lif.value = '20px'
      setTimeout(()=>{
        startMove()
      },2000)
    }
  })
}
//以下是巡查轨迹的代码
function createLuxianLayer(trackLine) {
  const trackFeature = new Feature({
    type: "track",
    geometry: trackLine,
  });
  const geoMarker = new Feature({
    type: "geoMarker",
    geometry: new Point(passCoordinates.value[0]),
  });
  geoMarker.setId("point");
  const startMarker = new Feature({
    type: "iconStart",
    geometry: new Point(passCoordinates.value[0]),
  });
  const endMarker = new Feature({
    type: "iconEnd",
    geometry: new Point(
      passCoordinates.value[passCoordinates.value.length - 1]
    ),
  });
  const styles = {
    track: new Style({ //轨迹样式
      stroke: new Stroke({
        width: 3,
        color: '#54ff9f',
      }),
    }),
    iconEnd: new Style({//终点
      image: new Icon({
        anchor: [0.5, 1],
        scale: 1,
        src: LuxianImg("endMark"),
      }),
    }),
    iconStart: new Style({//起点
      image: new Icon({
        anchor: [0.5, 1],
        src: LuxianImg("start"),
        scale: 1, //设置大小
      }),
    }),
    geoMarker: new Style({ //车标
      image: new Icon({
        src: LuxianImg("trackCar"),
        scale: 1,
        size: [32, 32],
        anchor: [0.5, 1],
        offsetY: "32",
      }),
    }),
  };
  trackLayer.value = new VectorLayer({
    source: new VectorSource({
      features: [trackFeature, geoMarker, startMarker, endMarker],
    }),
    style: (feature) => {
      return styles[feature.get("type")];
    },
    zIndex: 30,
  });
  map.value.addLayer(trackLayer.value);
}
function move(evt) {
  const frameState = evt.frameState;
  // 执行动画已经过了多少时间(秒)
  const timeout = (frameState.time - startTime.value) / 1000;
  let count = Math.round(speed * timeout);
  if (count >= passCoordinates.value.length - 1) {
    // 确保到达最后一个点位,并停止移动动画
    count = passCoordinates.value.length - 1;
    stopMove();
  }
  const point = trackLayer.value.getSource().getFeatureById("point");
  point.getGeometry().setCoordinates(passCoordinates.value[count]);
  map.value.render();
}
function startMove() {
  startTime.value = new Date().getTime();
  map.value.on("postrender", move);
  // 第一次需要手动调用一遍,否则不执行postcompose
  map.value.render();
}
function stopMove() {
  map.value.un("postrender", move);
  startMove()
}
function addTrack(coordinates) {
  const trackLine = new LineString(coordinates);
  // 轨迹在投影平面上的长度
  const trackLineLen = trackLine.getLength();
  // 使用轨迹线计算边界矩形
  var bounds = trackLine.getExtent();
  // 使用`fitBounds`方法应用边界
  map.value.getView().fit(bounds);
  // 当前平面的分辨率
  const resolution = map.value.getView().getResolution();
  // 点有可能是小数,要到终点需要手动添加最后一个点
  const pointCount = trackLineLen / (resolution * particle);
  for (let i = 0; i <= pointCount; i++) {
    passCoordinates.value.push(trackLine.getCoordinateAt(i / pointCount));
  }
  passCoordinates.value.push(coordinates[coordinates.length - 1]);
  map.value.setView(new View({
    center: [(parseFloat(coordinates[0][0]) + 0.03), parseFloat(coordinates[0][1])],
    projection: 'EPSG:4326',
    zoom: 14,
  }))
  createLuxianLayer(trackLine);
}
function removeTrak() {
  if (trackLayer.value && map.value) {
    map.value.removeLayer(trackLayer.value);
    passCoordinates.value = [];
    trackLayer.value = null;
  }
}
//车辆图标
function LuxianImg(name) {
  return new URL(`../../../assets/imgs/${name}.png`, import.meta.url).href;
}
//路线关闭
function lxHide(){
  lif.value = '-100%'
  removeTrak()
}

 css

.lujing-list{
    position: absolute;
    top: 330px;
    transform: translateY(-50%);
    display: flex;
    flex-direction: column;
    background: linear-gradient(180deg, rgba(28, 46, 105, 0.8) 0%, rgba(66, 97, 194, 0.8) 100%);
    backdrop-filter: blur(2px);
    border-radius: 5px;
    transition: left .8s;
    height: 450px;
    width: 315px;
    padding: 25px 15px;
    .bottomBg {
      background: url("@/assets/images/oneImage/wenluLeft.png") no-repeat center center;
      background-size: cover;
      position: absolute;
      width: 100%;
      height: 398px;
      bottom: 0;
      left: 0;
    }
    .head {
      display: flex;
      height: 30px;
      justify-content: space-between;
      align-items: center;
      padding-bottom: 10px;
      margin-bottom: 10px;
      .el-button--primary {
        background-color: #398AC2;
      }
    }
    .show-area{
      width: 100%;
      height: calc(100% - 40px);
      overflow: auto;
      position: relative;
      z-index: 1;
      color: #fff;
      .luxian-title{
        font-size: 18px;
        font-weight: bold;
      }
      .lx-area{
        p{
          margin: 0;
        }
        .pxia{
          text-align: center;
          font-size: 20px;
        }
      }
    }
  }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值