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

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

 

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

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
      );
    },

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

小红书APP出现闪退问题,电商erp系统接口测试怎么做?(一)

7月27日凌晨&#xff0c;部分网友反馈小红书APP出现闪退问题。对此&#xff0c;小红书客服微博发文称&#xff0c;如遇到小红书APP无法启动的情况&#xff0c;用户可前往AppStore下载最新版本。 大家在讨论崩溃原因时&#xff0c;提到大概是接口出现了问题&#xff0c;对于软件…

05-向量的意义_n维欧式空间

线性代数 什么是向量&#xff1f;究竟为什么引入向量&#xff1f; 为什么线性代数这么重要&#xff1f;从研究一个数拓展到研究一组数 一组数的基本表示方法——向量&#xff08;Vector&#xff09; 向量是线性代数研究的基本元素 e.g. 一个数&#xff1a; 666&#xff0c;…

企业大数据可视化案例专题分享-入门

一、什么是数据可视化&#xff1f; 基本概念&#xff1a;数据可视化是以图示或图形格式表示的数据。让决策者可以看到以直观方式呈现的分析&#xff0c;以便他们可以掌握困难的概念或识别新的模式。借助交互式可视化&#xff0c;可以使用技术深入挖掘图表和图形以获取更多详细…

Pytorch基础

文章目录 一、Pytorch简介二、安装2.1 安装GPU环境2.2 安装Pytorch2.3 测试 三、Tensor3.1 Tensor创建3.1.1 torch.tensor() && torch.tensor([])3.1.2 torch.randn && torch.randperm3.1.3 torch.range(begin,end,step)3.1.4 指定numpy 3.2 Tensor运算3.2.1 A…

开源Blazor UI组件库精选:让你的Blazor项目焕然一新!

今天给大家推荐一些开源、美观的Blazor UI组件库&#xff0c;这些优秀的开源框架和项目不仅能够帮助开发者们提高开发效率&#xff0c;还能够为他们的项目带来更加丰富的用户体验。 注&#xff1a;排名不分先后&#xff0c;都是十分优秀的开源框架和项目 ​Ant Design Blazor…

深度学习(34)—— StarGAN(1)

深度学习&#xff08;34&#xff09;—— StarGAN&#xff08;1&#xff09; 文章目录 深度学习&#xff08;34&#xff09;—— StarGAN&#xff08;1&#xff09;1. 背景2. 基本思路3. 整体流程4. StarGAN v2(1) 网络结构(2) mapping network(3) style encoder(4)Loss 和之前…

【机器学习】西瓜书习题3.5Python编程实现线性判别分析,并给出西瓜数据集 3.0α上的结果

参考代码 结合自己的理解&#xff0c;添加注释。 代码 导入相关的库 import numpy as np import pandas as pd import matplotlib from matplotlib import pyplot as plt导入数据&#xff0c;进行数据处理和特征工程 得到数据集 D { ( x i , y i ) } i 1 m , y i ∈ { 0 ,…

安装企业级高负载web服务器tomcat,并部署应用

web服务器Tocamt 1.Tocmat简介2.Tocmat安装1.安装jdk2.部署Tomcat1.配置环境变量2.启动tocmat3.Tomcat web管理功能 3.部署jpress应用 1.Tocmat简介 Tomcat是Apache软件基金会&#xff08;Apache Software Foundation&#xff09;的Jakarta 项目中的一个核心项目&#xff0c;由…

C. Binary String Copying - 思维

分析&#xff1a; 赛时我是直接模拟的&#xff0c;tle然后mle&#xff0c;补提&#xff0c;发现规律&#xff0c;每一个改变的字符串都只会对应一个需要改变的区间&#xff0c;例如第一个样例前两个101100 -> 011100和101100 -> 011100&#xff0c;对应区间在确定改变的范…

paddle实现获取pdf的内容

paddle实现获取pdf的内容 1. 环境安装2. 实现代码 源码链接 1. 环境安装 安装paddlepaddle gpu版本python -m pip install paddlepaddle-gpu -i https://pypi.tuna.tsinghua.edu.cn/simplecpu版本&#xff1a;python -m pip install paddlepaddle -i https://pypi.tuna.tsing…

实战:Prometheus+Grafana监控Linux服务器及Springboot项目

文章目录 前言知识积累什么是Prometheus什么是Grafana怎样完成数据采集和监控 环境搭建docker与docker-compose安装docker-compose编写 监控配置grafana配置prometheus数据源grafana配置dashboardLinux Host Metrics监控Spring Boot 监控 写在最后 前言 相信大家都知道一个项目…

云原生全栈体系(二)

Kubernetes实战入门 第一章 Kubernetes基础概念 一、是什么 我们急需一个大规模容器编排系统kubernetes具有以下特性&#xff1a; 服务发现和负载均衡 Kubernetes 可以使用 DNS 名称或自己的 IP 地址公开容器&#xff0c;如果进入容器的流量很大&#xff0c;Kubernetes 可以负…

SSL 证书过期巡检脚本 (Python 版)

哈喽大家好&#xff0c;我是咸鱼 之前写了个 shell 版本的 SSL 证书过期巡检脚本 &#xff08;文章&#xff1a;《SSL 证书过期巡检脚本》&#xff09;&#xff0c;后台反响还是很不错的 那么今天咸鱼给大家介绍一下 python 版本的 SSL 证书过期巡检脚本 &#xff08;完整代码…

王道《操作系统》学习(二)—— 进程管理(二)

2.1 处理机调度的概念、层次 2.1.1 调度的基本概念 2.1.2 调度的三个层次 &#xff08;1&#xff09;高级调度&#xff08;作业调度&#xff09; &#xff08;2&#xff09;中级调度&#xff08;内存调度&#xff09; 补充知识&#xff1a;进程的挂起状态和七状态模型 &#x…

SAP从放弃到入门系列之创建特殊库存转储预留

文章概览 一、思路二、过程2.1前台的主要过程&#xff1a;2.2 BAPI的实现过程&#xff1a; 之前写过几篇生产领料的思路包括代码&#xff0c;有兴趣的可以翻翻之前我发的文章。最近遇到既有项目专用物资、按单专用物资、通用物资合并领料的业务模式&#xff0c;所以领料的库存的…

VGG卷积神经网络-笔记

VGG卷积神经网络-笔记 VGG是当前最流行的CNN模型之一&#xff0c; 2014年由Simonyan和Zisserman提出&#xff0c; 其命名来源于论文作者所在的实验室Visual Geometry Group。 测试结果为&#xff1a; 通过运行结果可以发现&#xff0c;在眼疾筛查数据集iChallenge-PM上使用VGG…

什么是高级持续威胁(APT)攻击

目录 前言什么是高级持续威胁高级持续威胁攻击有哪些独特特征APT攻击的五个阶段APT检测及防护措施总结 前言 APT攻击是利用多个阶段和不同攻击技术的复合网络攻击。APT不是一时兴起2构思或实施的攻击。相反&#xff0c;攻击者故意针对特定目标定制攻击策略。并在较长时间内进行…

Excel·VBA定量装箱、凑数值金额、组合求和问题

如图&#xff1a;对图中A-C列数据&#xff0c;根据C列数量按照一定的取值范围&#xff0c;组成一个分组装箱&#xff0c;要求如下&#xff1a; 1&#xff0c;每箱数量最好凑足50&#xff0c;否则为47-56之间&#xff1b; 2&#xff0c;图中每行数据不得拆分&#xff1b; 3&…

webpack基础知识一:说说你对webpack的理解?解决了什么问题?

一、背景 Webpack 最初的目标是实现前端项目的模块化&#xff0c;旨在更高效地管理和维护项目中的每一个资源 模块化 最早的时候&#xff0c;我们会通过文件划分的形式实现模块化&#xff0c;也就是将每个功能及其相关状态数据各自单独放到不同的JS 文件中 约定每个文件是一…

Matlab对TMS320F28335编程-新建工程闪烁led灯

前言 工具&#xff1a;Matlab2022b Matlab对接C2000插件&#xff0c;下载连接如下 Embedded Coder Support Package for Texas Instruments C2000 Processors - File Exchange - MATLAB Central 在Matlab中加载此插件后&#xff0c;按照要求一步一步的进行就可以&#xff0c…