Vue实现leafletMap自定义绘制线段 并且删除指定的已绘制的点位

news2024/10/6 8:27:10

 效果:点击表格可实现选中地图点位,删除按钮点击可删除对应点位并且重新绘制线段,点击确定按钮 保存已经绘制的点位信息传给父组件 并且该组件已实现回显 

 

 完整的组件代码如下  文件名称为:

leafletMakePointYt
<!--
 * @Description: leaflet 地图选择点位 实现画线 页面
 * @Author: mhf
 * @Date: 2023-05-30 18:23:37
-->
<template>
  <el-dialog
    width="1300px"
    append-to-body
    v-dialog-out
    v-if="dialogVisible"
    :title="title"
    :visible.sync="dialogVisible"
    :close-on-click-modal="false"
    :before-close="hideDialog"
  >
    <div>
      <!-- 地图盒子 -->
      <div id="map"></div>

      <!-- 左侧坐标展示框 -->
      <div class="points-box">
        <!-- 顶部标题 -->
        <div class="points-box-title">
          <span> 线路坐标 </span>
        </div>

        <!-- 坐标展示表 -->
        <div class="points-box-table">
          <el-table
            highlight-current-row
            @current-change="handleCurrentChange"
            :data="pointsArr"
            style="width: 100%"
            :height="tableHeight"
          >
            <el-table-column label="#" type="index" />
            <el-table-column prop="lat" label="经度" width="158" />
            <el-table-column prop="lng" label="纬度" width="158" />
            <el-table-column
              label="操作"
              width="60"
              fixed="right"
              v-if="showBtn"
            >
              <template slot-scope="scope">
                <el-button type="text" size="small" @click="delRow(scope)">
                  删除</el-button
                >
              </template>
            </el-table-column>
          </el-table>
        </div>

        <!-- 坐标盒子 底部按钮组 -->
        <div v-if="showBtn" class="points-box-btn">
          <el-button type="" size="" @click="clearMapLine"> 清除</el-button>
          <el-button type="primary" size="" @click="makeMapLine">
            开始</el-button
          >
          <el-button type="primary" size="" @click="endMakeLine">
            结束</el-button
          >
        </div>
      </div>
    </div>

    <!-- 弹窗底部按钮组 -->
    <div v-if="showBtn" slot="footer" class="dialog-footer">
      <el-button @click="hideDialog">取 消</el-button>
      <el-button type="primary" @click="submitPoints()">确 定</el-button>
    </div>
  </el-dialog>
</template>

<script>
import L from "leaflet";
import "leaflet/dist/leaflet.css";
//  引入互联网地图插件
require("@/utils/leftletMap/leaflet.ChineseTmsProviders.js");
require("@/utils/leftletMap/tileLayer.baidu.js");
// 引入互联网地图纠偏插件
require("@/utils/leftletMap/leaflet.mapCorrection.min.js");

export default {
  name: "leafletMakePointYt",
  components: {},
  props: {
    showBtn: {
      type: Boolean,
      default: true,
    },
  },
  data() {
    return {
      dialogVisible: false,
      title: "",
      map: null,
      iconStyle: {
        icon: L.icon({
          iconUrl: require("/public/img/mapIcon/point.png"),
          iconSize: [12, 12],
          // iconAnchor: [19, 19],
          // popupAnchor: [0, -10]
        }),
      }, // 点位图标样式

      chooseIconStyle: {
        icon: L.icon({
          iconUrl: require("/public/img/mapIcon/marker.png"),
          iconSize: [30, 30],
          iconAnchor: [18, 22],
        }),
      }, // 表格中选中的点位图标样式

      startIconStyle: {
        icon: L.icon({
          iconUrl: require("/public/img/mapIcon/startPoint.png"),
          iconSize: [30, 30],
          iconAnchor: [18, 22],
        }),
      }, // 起点点位图标样式

      endIconStyle: {
        icon: L.icon({
          iconUrl: require("/public/img/mapIcon/endPoint.png"),
          iconSize: [30, 30],
          iconAnchor: [18, 22],
        }),
      }, // 终点点位图标样式

      polylineStyle: {
        color: "#FF6B00",
        weight: 4,
      }, // 线条样式
      pointsArr: [], // 标记点位列表 [{lat: 30, lng: 120}, {lat: 31, lng: 121}]
      pointsArrMarker: [], // 已经绘制的点位
      polylineArr: [], // 已经绘制多条线段

      chooseMarker: undefined, // 当前选中的点位
      tableHeight: 440,
      loading: false, // loading 动画
      loadingInstance: null,
    };
  },
  methods: {
    hideDialog() {
      this.dialogVisible = false;
      this.map.remove();
      this.map = null;
    },

    submitPoints() {
      if (this.pointsArr.length < 2) {
        this.$message.warning("请先绘制线路");
      } else {
        this.$emit("on-response", this.pointsArr); // 将绘制好的坐标传递给父组件
        this.hideDialog();
      }
    },

    showDialog(data) {
      this.dialogVisible = true;
      this.title = data.title;
      this.$nextTick(() => {
        /* 避免重复渲染 */
        if (!this.map) this.initMap();
        this.handleResize();

        if (data.data) {
          this.pointsArr = JSON.parse(data.data);
          /* 线段回显 */
          var polyline = L.polyline(this.pointsArr, this.polylineStyle).addTo(
            this.map
          );
          this.polylineArr.push(polyline);
          /* 点位回显 */
          this.pointsArr.forEach((item, index) => {
            var marker = L.marker([item.lat, item.lng], this.iconStyle).addTo(
              this.map
            ); // 添加标记点
            this.pointsArrMarker.push(marker);
          });
        }
      });
    },

    /**
     * @Event 方法
     * @description: 初始化 leaflet 地图
     * */
    initMap() {
      this.map = L.map("map", {
        center: [30.194637, 120.122247],
        zoom: 13,
        attributionControl: false, // 隐藏logo
        zoomControl: false, // 默认缩放控件(仅当创建地图时该 zoomControl 选项是 true)。
        crs: L.CRS.Baidu, // 用于 WMS 请求的坐标参考系统,默认为映射 CRS。 如果您不确定它的含义,请不要更改它。
      });
      L.control
        .zoom({
          position: "bottomright",
        })
        .addTo(this.map);
      L.tileLayer.baidu({ layer: "vec" }).addTo(this.map); // 添加底图
    },

    /**
     * @Event 方法
     * @description: 开始画线
     * */
    makeMapLine() {
      this.map.getContainer().style.cursor = "crosshair"; // 更改鼠标样式
      // let index = -1
      var marker, polyline;
      this.map.on("click", (e) => {
        // index++
        // if (index === 0) {
        /* 设置起点 */
        // L.marker([e.latlng.lat, e.latlng.lng], this.startIconStyle).addTo(this.map);
        /* 设置起点 */
        // } else {
        marker = L.marker([e.latlng.lat, e.latlng.lng], this.iconStyle).addTo(
          this.map
        ); // 添加标记点
        // }
        this.pointsArrMarker.push(marker);
        this.pointsArr.push(e.latlng); // 添加点位坐标至点位数组
        polyline = L.polyline(this.pointsArr, this.polylineStyle).addTo(
          this.map
        ); // 创建单条线段
        this.polylineArr.push(polyline);
      });
    },

    /**
     * @Event 方法
     * @description: 结束画线
     * */
    endMakeLine() {
      if (this.pointsArr === [] || this.pointsArr.length === 0) {
        this.$message.warning("请先绘制线路");
      } else {
        this.map.getContainer().style.cursor = "grab"; // 更改鼠标样式
        this.map.fitBounds(
          this.polylineArr[this.polylineArr.length - 1].getBounds()
        ); // 缩放地图以适应标记和线条
        this.map.on("mousedown", (e) => {
          this.map.getContainer().style.cursor = "grabbing"; // 更改鼠标样式
        });
        this.map.on("mouseup", (e) => {
          this.map.getContainer().style.cursor = "grab"; // 更改鼠标样式
        });
        this.map.off("click"); // 关闭点击事件
      }
    },

    /**
     * @Event 方法
     * @description: 移除线段和点位
     * */
    clearMapLine() {
      if (this.pointsArr === [] || this.pointsArr.length === 0) {
      } else {
        /* 移除点位 */
        this.pointsArrMarker.forEach((marker) => {
          this.map.removeLayer(marker);
        });
        /* 移除线段 */
        this.polylineArr.forEach((polyline) => {
          polyline.remove();
        });
        this.endMakeLine(); // 结束画线
        this.polylineArr = [];
        this.pointsArr = [];
      }
    },

    /**
     * @Event 方法
     * @description: 动态改变表格的高度
     * */
    handleResize() {
      const height = document.querySelector(".points-box-table").offsetHeight;
      this.tableHeight = height - 10;
    },

    /**
     * @Event 方法
     * @description: 表格单行选中事件,实现每次点击时都能删除上一次点击的图标
     * */
    handleCurrentChange(row) {
      if (this.chooseMarker) {
        this.map.removeLayer(this.chooseMarker);
      }
      this.chooseMarker = L.marker(
        [row.lat, row.lng],
        this.chooseIconStyle
      ).addTo(this.map); // 添加标记点
    },

    /**
     * @Event 方法
     * @description: 删除表格单行数据并且移除该点位
     * */
    delRow(row) {
      this.loading = true;
      this.$nextTick(() => {
        const target = document.querySelector(".el-dialog__body");
        let options = {
          lock: true,
          text: "重新绘制中...",
          spinner: "el-icon-loading",
          background: "rgba(0, 0, 0, 0.7)",
        };
        this.loadingInstance = this.$loading(options, target);
      });
      setTimeout(() => {
        this.loading = false;
        this.loadingInstance.close();

        /* 删除点位 */
        this.map.removeLayer(this.pointsArrMarker[row.$index]);
        this.pointsArrMarker.splice(row.$index, 1); // 已经绘制的点位
        this.pointsArr.splice(row.$index, 1); // 标记点位列表
        /* 删除点位 */

        /* 删除线段 */
        this.polylineArr.forEach((polyline) => {
          polyline.remove();
        });
        var polyline = L.polyline(this.pointsArr, this.polylineStyle).addTo(
          this.map
        );
        this.polylineArr.push(polyline);
        /* 删除线段 */
      }, 500);
    },
  },
  created() {},
  mounted() {
    window.addEventListener("resize", this.handleResize);
  },
  destroyed() {
    window.removeEventListener("resize", this.handleResize);
  },
};
</script>

<style lang="scss" scoped>
.dialog-footer {
  text-align: center;
}

#map {
  height: 68vh;
}

.points-box {
  width: 426px;
  height: 570px;
  position: absolute;
  top: 100px;
  z-index: 99999 !important;
  background-color: #fff;
  left: 40px;

  &-title {
    height: 40px;
    background-color: #1492ff;
    font-size: 18px;
    color: #ffffff;
    line-height: 40px;
    padding: 0 20px;
  }

  &-table {
    height: 490px;
  }

  &-btn {
    height: 50px;
    position: absolute;
    padding-bottom: 18px;
    bottom: 0;
    left: 0;
    right: 0;
    margin: auto;
    width: 80%;
    display: flex;
    justify-content: space-around;
    align-items: center;
  }
}
</style>
<el-form-item label="线路轨迹 : " prop="assetSection.point">
              <el-input
                v-model="formData.assetSection.point"
                disabled
                placeholder=""
              >
                <template slot="append">
                  <div class="choose-class" @click="showLeafletMap">
                    <i class="iconfont if-ditudingwei" /> <span>选择</span>
                  </div>
                </template>
              </el-input>
            </el-form-item>






    <leafletMakePointYt ref="leafletMakePointYt" @on-response="getPoints" />





// 打开弹窗 

   showLeafletMap() {
      let passData = {
        title: "选择线路轨迹",
        data: this.formData.assetSection.point,
      };
      this.$refs.leafletMakePointYt.showDialog(passData);
    },



// passData: {
title: "选择线路轨迹",
data: "[{"lat":30.19398904706604,"lng":120.1454230189172},{"lat":30.204226626758985,"lng":120.19285355280543},{"lat":30.22270148713875,"lng":120.13162504542244},{"lat":30.189494160206575,"lng":120.15490912569484}]"
}



// 接收弹窗的点位数据
    getPoints(data) {
      this.$set(this.formData.assetSection, "point", JSON.stringify(data));
      this.$set(this.formData.assetSection, "startLongitude", data[0].lng);
      this.$set(this.formData.assetSection, "startLatitude", data[0].lat);
      this.$set(
        this.formData.assetSection,
        "endLongitude",
        data[data.length - 1].lng
      );
      this.$set(
        this.formData.assetSection,
        "endLatitude",
        data[data.length - 1].lat
      );
    },

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/825696.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

小程序学习(六):全局配置

1.全局配置文件及常用的配置项 全局配置-window 2.小程序窗口的组成部分 3.了解window节点常用的配置项 4.设置导航栏的标题 设置步骤:app.json->window->navigationBarTitleText 5.设置导航栏的背景色 背景颜色不支持red这种文字 6.设置导航栏的标题颜色 注意:navigat…

山西电力市场日前价格预测【2023-08-03】

日前价格预测 预测明日&#xff08;2023-08-03&#xff09;山西电力市场全天平均日前电价为344.46元/MWh。其中&#xff0c;最高日前电价为395.01元/MWh&#xff0c;预计出现在19: 45。最低日前电价为314.42元/MWh&#xff0c;预计出现在03: 15。 价差方向预测 1&#xff1a;实…

CefInitialize初始化

结合代码以及查看exe生成目录的debug.log [0802/160846.105:ERROR:icu_util.cc(133)] Invalid file descriptor to ICU data received. setlocal mt.exe -nologo -manifest "D:/D-Pro/Test/t_Explore/t_Explore/lib/Resources/cefsimple.exe.manifest" "D:/D-P…

第一章 基本的图像操作和处理

文章目录 第一章 基本的图像操作和处理1.1PIL&#xff1a;Python图像处理类库1.1.1转图像格式1.1.2创建缩略图1.1.3复制和粘贴图像区域 1.2Matplotlib1.2.1绘制图像、点、线1.2.2图像轮廓和直方图 1.3NumPy1.3.1图像数组表示1.3.2灰度变换1.3.4直方图均衡化 1.4SciPy1.4.1图像模…

基于Yolov2深度学习网络的车辆检测算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1. 卷积神经网络&#xff08;CNN&#xff09; 4.2. YOLOv2 网络 4.3. 实现过程 4.4. 应用领域 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 MATLAB2022A 3.部分核心…

USB技术浅析

一、USB3.0 USB是史上定义出的最成功的PC外围互连技术&#xff0c;并且已经迅猛地被引入到CE和Mobile领域。仅仅在2006年&#xff0c;就有超过20亿USB设备出产&#xff0c;而现在已经有超过60亿的USB产品被安装。 而随着技术创新的不断前进&#xff0c;新式设备&#xff0c;媒…

在线考试系统springboot学生试卷问答管理java jsp源代码mysql

本项目为前几天收费帮学妹做的一个项目&#xff0c;Java EE JSP项目&#xff0c;在工作环境中基本使用不到&#xff0c;但是很多学校把这个当作编程入门的项目来做&#xff0c;故分享出本项目供初学者参考。 一、项目描述 在线考试系统springboot 系统有2权限&#xff1a;管理…

物联网工程开发实施,应该怎么做?

我这里刚好有嵌入式、单片机、plc的资料需要可以私我或在评论区扣个6 物联网工程的概念 物联网工程是研究物联网系统的规划、设计、实施、管理与维护的工程科学&#xff0c;要求物联网工程技术人员根 据既定的目标&#xff0c;依照国家、行业或企业规范&#xff0c;制定物联网…

Linux - 进程地址空间

引入 在学习C语言的时候&#xff0c;内存包括栈区、堆区、静态区 这个布局是内存吗&#xff1f; 不是&#xff01;&#xff01; 这是进程地址空间&#xff01; 下面测试一下&#xff1a; 11540是bash进程 我们修改一下源程序&#xff0c;在观察下结果 发现父进程的g_value的值不…

在terminal里面如何把图片从一个文件夹下面移动到另一个文件夹下面

使用命令行将图片从 /home/meiyi/Downloads/ 文件夹下移动到 Blog/blog/app/assets/images/ 文件夹下&#xff0c;可以按照以下步骤进行&#xff1a; 1. 打开 terminal 并进入 Blog/blog 目录下面 2.将图片移动到 app/assets/images/ 文件夹下面 可以使用mv命令将图片从 /ho…

xlrd与xlwt操作Excel文件详解

Python操作Excel的模块有很多&#xff0c;并且各有优劣&#xff0c;不同模块支持的操作和文件类型也有不同。下面是各个模块的支持情况&#xff1a; .xls.xlsx获取文件内容写入数据修改文件内容保存样式调整插入图片xlrd√√√xlwt√√√√√xlutils√√√√xlwings√√√√√…

虚拟云网络系列 | Antrea 应用于 VMware 方案功能简介(十二)

接续 Antrea 网络系列&#xff0c;接下来我想和大家讨论的是 Antrea 本身的两个网络与定址相关功能&#xff1a;Antrea Egress/Antrea IPAM。但在开始说明这两个机制前&#xff0c;先得讨论在原生 Kubernetes 方案内基础的网络与定址设计&#xff0c;通常在企业环境内会产生什么…

使用docker部署一个jar项目

简介: 通过docker镜像, docker可以在服务器上运行包含项目所需运行环境的docker容器, 在线仓库里有很多各个软件公司官方发布的镜像, 或者第三方的镜像. 如果我们需要使用docker把我们的应用程序打包成镜像, 别的机器上只要安装了docker, 就可以直接运行镜像, 而不需要再安装应…

建网站一般使用Windows还是liunx好?

建网站一般使用Windows还是liunx好&#xff1f; 1&#xff1b;服务器配置比较低时&#xff0c;最好使用linux系统。 对于一个电脑新手&#xff0c;刚开始做网站时&#xff0c;都会选择入门级的服务器&#xff0c;我刚开始做网站时&#xff0c;就是这样的。我购买了一台入门级服…

为什么需要智能工业自动化网络?如何搭建?

在当今快节奏的社会中&#xff0c;工业自动化变得越来越重要。传统的手动操作和生产方式已经不能满足现代工业的需求。因此&#xff0c;建设工业自动化已成为一个必然趋势。通过不断进步的新技术创建更高效、更可靠、更安全的智能工业自动化网络。在本文中&#xff0c;我们将讨…

【转】金融行业JR/T0197-2020《金融数据安全 数据安全分级指南》解读

原文链接&#xff1a;金融行业JR/T0197-2020《金融数据安全 数据安全分级指南》解读 《金融数据安全 数据安全分级指南》 解 读 随着IT技术的发展&#xff0c;银行的基础业务、核心流程等众多事务和活动都运营在信息化基础之上&#xff0c;金融机构运行过程中产生了大量的数字…

SE-Net注意力机制详解

📌本次任务:了解SE-Net原理 SE-Net 是 ImageNet 2017(ImageNet 收官赛)的冠军模型,是由WMW团队发布。具有复杂度低,参数少和计算量小的优点。且SENet 思路很简单,很容易扩展到已有网络结构如 Inception 和 ResNet 中。(这篇论文是2019年的,应该是后续做了更新) 一…

(Acwing)完全背包问题

有 N 种物品和一个容量是 V 的背包&#xff0c;每种物品都有无限件可用。 第 ii 种物品的体积是 vi&#xff0c;价值是 wi。 求解将哪些物品装入背包&#xff0c;可使这些物品的总体积不超过背包容量&#xff0c;且总价值最大。 输出最大价值。 输入格式 第一行两个整数&am…

远程连接身份验证错误,又找不到加密Oracle修正

一、问题描述 远程连接服务器出现了错误&#xff0c;错误信息为&#xff1a;远程连接身份验证错误&#xff0c;又找不到加密Oracle修正。 二、原因分析 出错原因&#xff1a;Windows的CVE-2018-0886 的 CredSSP 更新将CredSSP 身份验证协议默认设置成了“缓解”&#xff0c;…

右键文件夹 ------- 打开 vscode的方法

1、右键vscode点击属性 2、这是地址栏&#xff0c;一会复制即可 3、新建一个txt文件,将这个复制进去 Windows Registry Editor Version 5.00[HKEY_CLASSES_ROOT\*\shell\VSCode] "Open with Code" "Icon""D:\\Microsoft VS Code\\Code.exe"[HKE…