leaflet以CAD图片为底图,实现路径导航等功能

需求背景:甲方需要在一些CAD图纸上动态展示特定路线导航,比如从一个房间,到另外一个房间的路径,需要显示出路径,因为以前没有接触过这类特定需求,所以先暂时调研了一下,并尝试做个demo给甲方演示。

刚开始的想法是,通过H5的canvas画布手动画出来,自己也尝试过了,但效果不是很理想,再后来调研到leaflet可以导入图片作为底图,因为其本身就是做GIS的,有点线面的各种操作,比如打点,连线,绘制区域图层等等,而且以前我也用过leaflet做gis,比较熟悉,所以决定用leaflet尝试做个demo

点击展示路径后:

实现思路:首先npm install leaflet,也可以CDN 引入,如果不清楚可以搜索leaflet安装与使用,安装完成后,在组件里面引用,再在组件的onMounted里面去创建地图实例,然后再调用leaflet的一些切换底图的api,并以像素px为坐标系单位,图片左下角为坐标系原点(不知道可不可以换成常规的x为横轴,y为竖轴,没试过,大家可以自己查leaflet文档调研一下),再手动量几个点位(基于下面图片显示的坐标系),再定义一些渲染点与点之间的连线方法,以及使用css3的动画来控制线条出现的时机,用来做到路径导航的效果,具体的方法和说明,源代码上都有,可以仔细研究

代码如下:

<template>
  <div>
    <a-button type="primary" @click="ShowLine">展示路径</a-button>
    <a-button type="primary" @click="removeLine" style="margin-left: 10px"
      >移除路径</a-button
    >
    <div id="map"></div>
  </div>
</template>

<script setup>
import button from "ant-design-vue";
import { onMounted, ref } from "vue";
import L from "leaflet";
import "leaflet/dist/leaflet.css";
import cadImg from "../assets/cad2.jpg";

// 定义三个点的坐标
const points = ref([
/*   [338, 465], // 第一个点
  [55, 467], // 第二个点
  [58, 172], // 第二个点
  [187, 172], // 第二个点
  [187, 97], // 第二个点
  [280, 97], // 第二个点
  [280, 172], // 第二个点
  [337, 172], // 第二个点 */
  
  [40, 467], // 第一个点
[338, 465], // 第一个点
[338, 172],
[187, 172],
[187, 97],
[110, 97],
[110, 172],
[40, 172],


]);

// 初始化地图
let map;
let line;

// 移除路径
const removeLine = () => {
  if (line) {
    map.removeLayer(line); // 从地图上移除线条
    line = null; // 清空线条引用
  }
};
/*  展示路径 */
const ShowLine = () => {
  // 创建连线
  line = L.polyline(points.value, {
    color: "blue",
    weight: 5,
    className: "animated-line", // 添加CSS类以实现动画
  }).addTo(map);
  /* drawLine(); */
};

onMounted(() => {
  // 创建地图实例
  map = L.map("map", {
    crs: L.CRS.Simple, // 使用简单坐标系
    zoomControl: false, // 禁用缩放控件
    scrollWheelZoom: false, // 禁用鼠标滚轮缩放
    doubleClickZoom: false, // 禁用双击缩放
    touchZoom: false, // 禁用触摸缩放
    boxZoom: false, // 禁用框选缩放
    keyboard: false, // 禁用键盘快捷键缩放
  }).setView([0, 0], 0);

  // 加载平面图
  const imageBounds = [
    [0, 0],
    [391, 640],
  ];
  L.imageOverlay(cadImg, imageBounds).addTo(map);
  map.fitBounds(imageBounds);
});

// 动态绘制连线
const drawLine = () => {
  const linePoints = []; // 存储连线的点
  let currentPointIndex = 0; // 当前连接的点的索引
      linePoints.push(...points.value);
      line.setLatLngs(linePoints); // 更新连线的点
  /* const interval = setInterval(() => {
    if (currentPointIndex < points.value.length) {
      // 将当前点添加到连线中
      linePoints.push(points.value[currentPointIndex]);
      line.setLatLngs(linePoints); // 更新连线的点
      currentPointIndex++;
    } else {
      clearInterval(interval); // 停止动画
    }
  }, 500); // 每500ms连接一个点 */
};
</script>

<style>
#map {
  height: 800px; /* 调整地图高度 */
  width: 100%; /* 调整地图宽度 */
}

/* 定义动画效果 */
.animated-line {
  stroke-dasharray: 4000; /* 控制虚线的长度 */
  stroke-dashoffset: 4000; /* 初始偏移量 */
  animation: dash 32s linear forwards; /* 动画时长和效果 */
}

@keyframes dash {
  to {
    stroke-dashoffset: 0;
  }
}
</style>

有些点是需要注意的:引入底图时,不能放底图的相对路径,需要import导入进来,或者直接把底图用在线工具转成base64格式,再放到L.imageOverlay(cadImg, imageBounds).addTo(map);里面去。

另外,这些点的坐标,是我手动通过ps工具量出来的,因为后端说到时候能给到前端,所以我就没思考坐标与CAD图里的建筑图啥的是否有关系。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值