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


完整的组件代码如下 文件名称为:
leafletMakePointYt
<!--* @Description: leaflet 地图选择点位 实现画线 页面* @Author: mhf* @Date: 2023-05-30 18:23:37
-->
<template><el-dialogwidth="1300px"append-to-bodyv-dialog-outv-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-tablehighlight-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-columnlabel="操作"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, // 隐藏logozoomControl: 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 = -1var 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-inputv-model="formData.assetSection.point"disabledplaceholder=""><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);},

相关文章:
Vue实现leafletMap自定义绘制线段 并且删除指定的已绘制的点位
效果:点击表格可实现选中地图点位,删除按钮点击可删除对应点位并且重新绘制线段,点击确定按钮 保存已经绘制的点位信息传给父组件 并且该组件已实现回显 完整的组件代码如下 文件名称为: leafletMakePointYt <!--* Descripti…...
ChatGPT辅助写论文:提升效率与创造力的利器
写作是人类最重要的交流方式之一,也是学术研究中不可或缺的环节。然而,写作并不是一件容易的事情,尤其是对于科研人员来说,他们需要花费大量的时间和精力来撰写高质量的论文,并且面临着各种各样的挑战,如语…...
面试攻略,Java 基础面试 100 问(六)
JAVA 泛型 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。泛型的本 质是参数化类型,也就是说所操作的数据类型被指定为一个参数。比如我们要写一个排序方法, 能够对整型数组、字符串数组甚至其他任何类型的…...
图解系列 DNS查找过程和DNS缓存
DNS 充当地址簿。它将人类可读的域名 (google.com) 转换为机器可读的 IP 地址 (142.251.46.238)。 开局一张图 来自:https://xiaolishen.medium.com/the-dns-lookup-journey-240e9a5d345c 寻址流程 查询浏览器缓存:当你输入一个域名后,浏览…...
《吐血整理》高级系列教程-吃透Fiddler抓包教程(21)-如何使用Fiddler生成Jmeter脚本-上篇
1.简介 我们知道Jmeter本身可以录制脚本,也可以通过BadBoy,BlazeMeter等工具进行录制,其实Fiddler也可以录制Jmter脚本(而且有些页面,由于安全设置等原因,使用Jmeter直接无法打开录制时,这时就…...
vim中出现复制不对齐-乱码问题
不对齐解决: 使用纯文本模式粘贴:在进入 Vim 编辑器后,先按下 :set paste 进入插入模式,然后再进行粘贴操作。这样可以确保粘贴的文本以纯文本格式插入,而不会触发自动缩进或其他格式化操作 中文乱码问题:…...
华为OD机考真题--单词接龙--带答案
2023华为OD统一考试(AB卷)题库清单-带答案(持续更新)or2023年华为OD真题机考题库大全-带答案(持续更新) 题目描述: 单词接龙的规则是: 用于接龙的单词首字母必须要前一个单词的尾字母…...
排序进行曲-v3.0
文章目录 小程一言归并排序步骤举例总结时间复杂度分析:空间复杂度分析:注意 应用场景总结 实际举例Other 代码实现结果解释 小程一言 这篇文章是在排序进行曲2.0之后的续讲, 这篇文章主要是对归并排序进行细致分析,以及操作。 希…...
编辑列表操作时的一些思考,关于全量和增量操作
假设我有一个这样的页面,需要对用户的信息做编辑操作 角色下面有一些菜单项,通过一张角色-菜单关系表来维护,那么我要在编辑用户后也要对用户角色关系表做修改,是经过两次比较分别计算出需要增加或者删除的角色用户关系࿰…...
【python】Python tkinter库实现重量单位转换器的GUI程序
文章目录 前言学到什么?导入模块和库创建一个GUI窗口定义函数 from_kg()创建标签、输入框、文本框和按钮设置组件的布局运行窗口循环完整代码运行效果结束语 前言 这段代码是一个简单的重量单位转换器的 GUI 程序,使用了 Python 的 tkinter 库来创建图形界面。该程…...
CVPR2023新作:源数据集对迁移学习性能的影响以及相应的解决方案
Title: A Data-Based Perspective on Transfer Learning (迁移学习的基于数据的观点) Affiliation: MIT (麻省理工学院) Authors: Saachi Jain, Hadi Salman, Alaa Khaddaj, Eric Wong, Sung Min Park, Aleksander Mądry Keywords: transfer learning, source dataset, dow…...
《TCP IP 网络编程》第十五章
第 15 章 套接字和标准I/O 15.1 标准 I/O 的优点 标准 I/O 函数的两个优点: 除了使用 read 和 write 函数收发数据外,还能使用标准 I/O 函数收发数据。下面是标准 I/O 函数的两个优点: 标准 I/O 函数具有良好的移植性标准 I/O 函数可以利用…...
新特性解读 | MySQL 8.0 字段信息统计机制
作者通过一个案例详细说明了 MySQL 8.0 字段信息统计机制的相关参数和使用方式。 作者:杨奇龙 网名“北在南方”,资深 DBA,主要负责数据库架构设计和运维平台开发工作,擅长数据库性能调优、故障诊断。 本文来源:原创投…...
基于Java+Swing实现超级玛丽游戏
基于JavaSwing实现超级玛丽游戏 一、系统介绍二、功能展示三、其他系统 一、系统介绍 超级玛丽小游戏的JAVA程序,进入游戏后首先按空格键开始,利用方向键来控制的马里奥的移动,同时检测马里奥与场景中的障碍物和敌人的碰撞,并判断…...
Day12-1-Webpack前端工程化开发
Webpack前端工程化 1 案例-webpack打包js文件 1 在index.html中编写代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><me…...
JUnit教程_编程入门自学教程_菜鸟教程-免费教程分享
教程简介 JUnit是一个Java语言的单元测试框架。它由Kent Beck和Erich Gamma建立,逐渐成为源于Kent Beck的sUnit的xUnit家族中最为成功的一个。 JUnit有它自己的JUnit扩展生态圈。多数Java的开发环境都已经集成了JUnit作为单元测试的工具。JUnit是由 Erich Gamma 和…...
Hive 安装介绍
介绍 Hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表,并提供类SQL查询功能。 其本质是将SQL转换为MapReduce的任务进行运算,底层由HDFS来提供数据的存储,说白了hive可以理解为一个将SQL转换为Ma…...
npm ERR! code EPERM npm ERR! syscall unlink npm ERR!错误解决方法
npm ERR! code EPERM npm ERR! syscall unlink npm ERR!错误解决方法 1、问题描述2、解决方法 1、问题描述 由于之前电脑系统的原因,电脑重置了一下,之前安装的环境都没了,然后在重新安装node.js后在使用npm安装时总是报如下错误:…...
redis 高级篇4 分布式锁
一 redis架构图 1.1 redis的架构图 1.2 分布式锁满足条件 1.独占性;2.高可用;3.防死锁;4.不乱抢;5.重入性 二 分布式锁的案例情况 2.1 分布式锁1:单机分布式部署 描述: 使用lock锁和synchronized,单机…...
TPU-NNTC 编译部署LPRNet 车牌识别算法
TPU-NNTC 编译部署LPRNet 车牌识别算法 注意: 由于SOPHGO SE5微服务器的CPU是基于ARM架构,以下步骤将在基于x86架构CPU的开发环境中完成 初始化开发环境(基于x86架构CPU的开发环境中完成)模型转换 (基于x86架构CPU的开发环境中完成) 处理后的LPRNet 项…...
量子机器学习在医疗影像中的技术迷思与测试验证陷阱
当量子计算遭遇医学影像近年来,"量子赋能医疗影像"成为热门概念,宣称通过量子算法(如QSVM、量子卷积)可大幅提升病灶识别精度和图像重建效率。然而,作为软件测试从业者,我们需警惕技术炒作背后的…...
Qwen3-14B日志分析教程:ELK栈收集推理请求、响应、错误全链路追踪
Qwen3-14B日志分析教程:ELK栈收集推理请求、响应、错误全链路追踪 1. 为什么需要日志分析 当你在私有化部署Qwen3-14B模型时,可能会遇到各种问题:为什么推理速度突然变慢了?为什么API返回了错误响应?哪些请求消耗了最…...
零基础玩转mxbai-embed-large-v1:6大核心功能实战,从向量化到摘要生成
零基础玩转mxbai-embed-large-v1:6大核心功能实战,从向量化到摘要生成 1. 引言:为什么选择mxbai-embed-large-v1? mxbai-embed-large-v1是当前自然语言处理领域的一颗新星,这款多功能句子嵌入模型在MTEB基准测试中表…...
保姆级教程:用STM32的定时器输入捕获功能,手把手教你解码任意红外遥控器
STM32定时器输入捕获实战:从零解码未知协议红外遥控信号 红外遥控技术在家电控制领域已有数十年历史,但面对市面上五花八门的遥控协议,开发者常常陷入协议适配的泥潭。本文将带你突破协议限制,利用STM32的定时器输入捕获功能&…...
HunyuanVideo-Foley 企业级架构设计:基于Agent的分布式音效生成调度系统
HunyuanVideo-Foley 企业级架构设计:基于Agent的分布式音效生成调度系统 1. 引言:音效生成的企业级挑战 想象一下这样的场景:一家大型视频平台每天需要为上万条视频自动生成匹配的音效。传统单机方案面临三大难题:生成速度跟不上…...
Phi-4-mini-reasoning效果展示:含单位换算、科学计数法的复合型数学题求解
Phi-4-mini-reasoning效果展示:含单位换算、科学计数法的复合型数学题求解 1. 模型能力概览 Phi-4-mini-reasoning是一款专注于推理任务的文本生成模型,特别擅长处理需要多步逻辑推导的问题。与通用聊天模型不同,它更专注于"问题输入→…...
Python并发安全性重构白皮书(GIL禁用场景下的原子操作黄金标准)
第一章:Python并发安全性重构白皮书(GIL禁用场景下的原子操作黄金标准)当通过 PyPy、Cython(启用 nogil)、或 Python 3.12 的实验性子解释器(PEP 684)等路径绕过全局解释器锁(GIL&am…...
告别低效:用快马ai一键生成can总线数据分析与统计脚本
在汽车电子和嵌入式系统开发中,CAN总线数据的分析是个高频需求。无论是调试车载网络问题,还是优化通信性能,都离不开对海量CAN帧数据的处理。但手动写解析脚本不仅耗时,还容易遗漏关键细节。最近我发现用InsCode(快马)平台的AI辅助…...
LFM2.5-1.2B-Thinking-GGUF入门必看:轻量模型在离线环境中的安全合规部署
LFM2.5-1.2B-Thinking-GGUF入门必看:轻量模型在离线环境中的安全合规部署 1. 模型概述 LFM2.5-1.2B-Thinking-GGUF是Liquid AI推出的轻量级文本生成模型,专为低资源环境设计。这个1.2B参数的模型采用GGUF格式,能够在各种边缘设备上高效运行…...
经验值|React 实时数据图表性能为什么会越来越卡?
在使用 React 和 Highcharts 创建实时图表时,性能下降通常与以下几个因素有关:频繁更新状态:如果你频繁更新图表的数据状态,React 可能会进行多次重渲染,导致性能下降。建议使用 useRef 来引用图表实例,避免…...
