uniapp地图电子围栏(多边形)绘制和编辑

uniapp地图电子围栏(多边形)绘制和编辑

  • 背景
  • 实现思路
  • 代码实现
  • 注意事项
  • 尾巴

背景

最近项目中需要在地图上进行电子围栏的绘制和编辑,这里将实现的思路给大家分享下。由于uniapp官方提供的map组件功能不全,还有在APP端(非nvue)还存在层级问题,所以这里就不考虑使用官方map组件,而是使用renderjs来实现。renderjs中如何使用地图可以参考uniapp地图开发(APP,H5)之前这一篇文章。

在开始实现之前,我们先看下效果图
请添加图片描述

实现思路

1、我们首先需要在页面展示地图底板
2、DOM中添加四个操作按钮
3、监听地图点击事件,以地图中心点和点击点为两个点生成多边形
4、实现清除、编辑、保存、确定等按钮逻辑

代码实现

其实我们写代码是要先有思路,我们的代码也是根据上面的思路来分步来实现。
接下来就直接上主逻辑页面代码(second.vue)。

<template>
	<div id='container' class="map" :style="'height:'+maph+'px'">
		<view :originPolygon="originPolygon" :change:originPolygon="renderJS.receiveOriginPolygon" />
	</div>
</template>

<script>
	export default {
		data() {
			return {
				maph: 0,
				//如果需要编辑多边形,传进来多边形字符串
				originPolygon: '',
				polygon: []
			}
		},
		onLoad(option) {
			this.maph = uni.getSystemInfoSync().windowHeight
			this.originPolygon = option.polygon || ''
		},
		methods: {
			polygonSave(result) {
				this.polygon = result
				const eventChannel = this.getOpenerEventChannel();
				eventChannel.emit('polygonResult',{
					result: JSON.stringify(this.polygon)
				})
				uni.navigateBack({
					delta: 1
				})
			}
		}
	}
</script>
<script module="renderJS" lang="renderjs">
	let map = null
	//是否编辑模式
	let isEditMode = false
	//其他页面传入的多边形,用作多边形编辑
	let originPolygon = null
	//多边形的关键点
	let path = []
	//多边形编辑器
	let polygonEditor = null
	let ownerInstance = null
	//选定并保存好的多边形
	let polygonSave = []
	//编辑还未保存的多边形
	let polygonSaveTemp = []
	export default {
		data() {
			return {

			}
		},
		mounted() {
			window._AMapSecurityConfig = {
				securityJsCode: '高德申请的securityJsCode',
			}
			if (typeof window.AMap == 'function') {
				this.initAmap();
			} else {
				// 动态引入较大类库避免影响页面展示
				const script = document.createElement('script');
				script.src = 'https://webapi.amap.com/maps?v=2.0&key=高德申请的key';
				script.onload = this.initAmap.bind(this);
				document.head.appendChild(script);
			}
		},
		//页面卸载清空
		onUnload() {
			map = null
			//是否编辑模式
			isEditMode = false
			//其他页面传入的多边形,用作多边形编辑
			originPolygon = null
			//多边形的关键点
			path = []
			//多边形编辑器
			polygonEditor = null
			ownerInstance = null
			//选定并保存好的多边形
			polygonSave = []
			//编辑还未保存的多边形
			polygonSaveTemp = []
		},
		methods: {
			//获取到传进来的多边形
			receiveOriginPolygon(newValue, oldValue, ownerVm, vm) {
				if (!ownerInstance) {
					ownerInstance = ownerVm
				}
				if(!newValue){
					return
				}
				originPolygon = JSON.parse(newValue)
				isEditMode = true
			},
			initAmap(e, ownerVm) {
				map = new AMap.Map("container", {
					zoom: 12, //设置地图显示的缩放级别
					viewMode: '2D' //设置地图模式
				});
				map.on('click', (e) => {
					if (!originPolygon) {
						if (isEditMode) {
							if (path.length <= 0) {
								path.push(map.getCenter())
							}
							if (polygonEditor) {
								polygonEditor.close()
							}
							map.clearMap()
							path.push(new AMap.LngLat(e.lnglat.lng, e.lnglat.lat))
							this.drawPolygon()
						} else {
							alert('请点击编辑按钮进行绘制')
						}
					}else {
						if (polygonEditor) {
							polygonEditor.close()
						}
						map.clearMap()
						path.push(new AMap.LngLat(e.lnglat.lng, e.lnglat.lat))
						this.drawPolygon()
					}
				})
				map.on('complete', () => {
					console.log('地图加载完成')
					if (originPolygon) {
						originPolygon.forEach(ele => {
							path.push(ele)
						})
					}
					this.drawPolygon()
				})
				this.initDivs()
			},
			//画多边形
			drawPolygon() {
				if(path.length <= 0){
					return
				}
				let polygon = new AMap.Polygon({
					path: path, //路径
					fillColor: "#FF615F", //多边形填充颜色
					fillOpacity: 0.2,
					strokeStyle: 'dashed',
					strokeWeight: 2, //线条宽度,默认为 2
					strokeColor: "#FF615F", //线条颜色
				});
				//多边形 Polygon对象添加到 Map
				map.add(polygon);
				//将覆盖物调整到合适视野
				map.setFitView([polygon])
				map.plugin(["AMap.PolygonEditor"], function() {
					//实例化多边形编辑器,传入地图实例和要进行编辑的多边形实例
					polygonEditor = new AMap.PolygonEditor(map, polygon);
					//开启编辑模式
					polygonEditor.open();
					polygonEditor.on('end', (e) => {
						let polygonPaths = e.target.getPath()
						if (polygonPaths.length <= 1) {
							return
						}
						//清除了
						if (path.length <= 0) {
							polygonSaveTemp = []
							return
						}
						let paths = []
						polygonPaths.forEach(ele => {
							let temp = [ele.lng, ele.lat]
							paths.push(temp)
						})
						polygonSaveTemp = paths
					})
				});
			},
			//创建单个div
			createDiv(inner) {
				let div = document.createElement('div');
				div.style.width = '70px';
				div.style.height = '30px';
				div.style.background = '#FFFFFF';
				div.style.boxShadow = 'box-shadow: 0px 0px 3px 1px rgba(0, 0, 0, 0.1)';
				div.style.borderRadius = '10px';
				div.style.fontSize = '15px';
				div.style.lineHeight = '30px';
				div.style.textAlign = 'center';
				div.innerHTML = inner
				return div
			},
			initDivs() {
				const div = document.createElement('div');
				div.style.display = 'flex';
				div.style.flexDirection = 'row';
				div.style.width = 'calc(100% - 40px)';
				div.style.alignItems = 'center';
				div.style.height = '40px';
				div.style.justifyContent = 'space-between';
				div.style.position = 'fixed';
				div.style.bottom = '40px';
				div.style.left = '20px';
				div.style.fontSize = '30px';
				div.style.zIndex = 999
				document.body.appendChild(div);

				const clearDiv = this.createDiv('清除')
				div.appendChild(clearDiv)
				clearDiv.addEventListener('click', function() {
					path = []
					polygonSave = []
					polygonSaveTemp = []
					originPolygon = null
					if (polygonEditor) {
						polygonEditor.close()
						polygonEditor = null
					}
					if (map) {
						map.clearMap()
					}
					console.log('清除')
				});

				const editDiv = this.createDiv('编辑')
				div.appendChild(editDiv)
				editDiv.addEventListener('click', function() {
					isEditMode = true
					if (polygonEditor) {
						polygonEditor.open()
					}
					console.log('编辑')
				});

				const saveDiv = this.createDiv('保存')
				div.appendChild(saveDiv)
				saveDiv.addEventListener('click', function() {
					isEditMode = false
					if (polygonEditor) {
						polygonEditor.close()
					}
					if(polygonSaveTemp){
						polygonSave = polygonSaveTemp
					}
					setTimeout(function() {
						if (map) {
							map.setFitView()
						}
					}, 200);
					console.log('保存')
				});

				const confirmDiv = this.createDiv('确定')
				div.appendChild(confirmDiv)
				confirmDiv.addEventListener('click', function() {
					if (polygonSave && polygonSave.length > 0) {
						ownerInstance.callMethod('polygonSave', polygonSave)
					}else {
						if(polygonEditor){
							alert('请先保存多边形')
						}else {
							alert('还未绘制多边形')
						}
					}
					console.log('确定')
				});

			}
		}
	}
</script>
<style>
	.map {
		z-index: 1;
		height: 100%;
		width: 750rpx;
	}
</style>

还有一个测试页面index.vue,这个页面主要是一个按钮和点击事件,这里我就只写点击事件了。

//代码省略...
goSecond(){
	uni.navigateTo({
		url: `/pages/second/second?polygon=${this.polygon}`,
		events: {
			polygonResult: res=>{
				//回调结果,页面展示用
				this.polygon = res.result
			}
		}
	})			
}
//代码省略...

注意事项

我这里使用的是高德地图,开发这需要去高德官网申请应用的key,并填入文章中代码标识处。支持电子围栏的绘制和已有电子围栏的展示和编辑。通过高德地图API,还可以实现矩形和圆形等多种电子围栏实现。由于使用renderjs实现,只支持H5和APP,小程序不支持。

尾巴

今天的文章就到这里了,希望能给大家帮助,如果喜欢我的文章,欢迎给我点赞,评论,关注,谢谢大家!
PS:很多博主都把文章设置为关注后才能查看,感觉这样有点恶心。如果我的文章切实能给各位观众老爷们带来帮助,真心求点个关注,再次感谢各位观众老爷们了。

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

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

相关文章

Java面试题:Spring框架除了IOC和AOP,还有哪些好玩的设计模式?

Spring是一个基于Java的企业级应用程序开发框架&#xff0c;它使用了多种设计模式来实现其各种特性和功能。本文将介绍一些在Spring中使用的常见设计模式以及相应的代码示例和说明。 单例模式 单例模式是Spring中最常用的设计模式之一。在ApplicationContext中&#xff0c;Bean…

5.8 5.9_C语言(初阶)

1、函数 1.1 函数是什么 数学中就见过函数&#xff0c;例&#xff0c;f(x)2*x1,如果给一个不同的数x&#xff0c;就能得到一个不同的f(x),这就是数学中的函数&#xff0c;其实在C语言中跟这非常相似。 维基百科中对函数的定义&#xff1a;子程序 在计算机科学中&#xff0c…

如何对SQL Server中的敏感数据进行加密解密?

为什么需要对敏感数据进行加密&#xff1f; 近几年有不少关于个人数据泄露的新闻&#xff08;个人数据通常包含如姓名、地址、身份证号码、财务信息等&#xff09;&#xff0c;给事发公司和被泄露人都带来了不小的影响。 许多国家和地区都出台了个人数据保护的法律法规&#…

25考研英语长难句Day03

25考研英语长难句Day03 【a.词组】【b.断句】 多亏了电子学和微力学的不断小型化&#xff0c;现在已经有一些机器人系统可以进行精确到毫米以下的脑部和骨骼手术&#xff0c;比技术高超的医生用手能做到的精确得多。 【a.词组】 词组翻译thanks to多亏了&#xff0c;由于cont…

vm 虚拟机 Debian12 开启 root、ssh 登录功能

前言&#xff0c;安装的时候语言就选中文就好了。选择中文&#xff0c;在安装的时候就可以选择国内 163 的源。 开启 ssh 功能 先提权&#xff0c;用 root 账户 su安装 ssh 安装 ssh-server apt install openssh-server启动 ssh systemctl start ssh查看 ssh 状态 systemctl st…

淘宝店铺运营爆流课:助你打造高流量店铺,实现销售持续增长(52节课)

课程目录 01【开店类型第1课】货架式店铺.mp4 02【开店类型第2课】短视频店铺.mp4 03【开店类型第3课】直播型店铺.mp4 04【店铺基础操作第1课】如何发布一个成功的宝贝.mp4 05【店铺基础操作第2课】商品SKU设置技巧及库存设置方法.mp4 06【标题】如何制作一个爆款标题.mp…

网络安全大神是怎么炼成的

首先&#xff0c;兴趣是最好的老师&#xff0c;如果你不感兴趣&#xff0c;建议换一个有兴趣的专业&#xff0c;其次&#xff0c;再来说说你是对信息安全感兴趣&#xff0c;想往安全方面走的&#xff0c;我这边给你一些学习建议。 首先&#xff0c;安全这方面的前景是很好的&a…

TopOn 正式聚合Kwai 旗下程序化广告平台——Kwai Network

**我们非常高兴的宣布&#xff0c;TopOn SDK 近日已正式聚合Kwai Network。**作为Kwai 旗下的程序化广告平台&#xff0c;Kwai Network 通过优质的变现能力及产品能力&#xff0c;为广大开发者提供高效及时的服务。 TopOn 聚合平台与Kwai Network 正式完成接入后&#xff0c;开…

上海市嘉定区三德广场屋顶气膜篮球馆

上海市嘉定区三德广场屋顶气膜篮球馆为现代化城市综合体增添了一处先进、环保的运动设施。这座篮球馆不仅为广场周边居民提供了一个全天候的运动场所&#xff0c;也为嘉定区的体育爱好者带来了全新的健身体验。作为轻空间&#xff08;江苏&#xff09;膜科技有限公司&#xff0…

Linux系统 的持续学习

昨天学习了目录结构、补充命令和配置网络&#xff0c;其中配置网络用了nat方法&#xff0c;今天学习用桥接方法&#xff0c;通配符、正则表达式的一部分内容。 桥接模式 如果重网卡失败&#xff1a; 1.检查配置文件是否正确 2.检查虚拟器编辑器有没有选对&#xff08;网卡类…

谷歌外贸seo优化怎么做?

一般有两种选择&#xff0c;在大型电商平台开展业务&#xff0c;如亚马逊&#xff0c;阿里巴巴等平台&#xff0c;也可以选择搭建自己的独立站 选择在大型电商平台可以方便迅速建立起自己的商铺&#xff0c;不需要考虑太多交易&#xff0c;支付&#xff0c;物流等方面的问题&am…

[AI智能摄像头]RV1126部署yolov5并加速

导出onnx模型 yolov5官方地址 git clone https://github.com/ultralytics/yolov5 利用官方命令导出python export.py --weights yolov5n.pt --include onnx 利用代码导出 import os import sys os.chdir(sys.path[0]) import onnx import torch sys.path.append(..) from m…

[智能AI摄像头]RV1126适配3inch mipi屏幕

3寸屏幕 硬件平台 3寸屏&#xff1a;ST7701S驱动芯片&#xff0c;mipi接口&#xff0c;2lane rv1126&#xff1a;易佰纳38板、正点原子rv1126开发板 所需资料 《屏幕规格书》、《开发板原理图》、《屏幕初始化序列》、《ST7701S数据手册》《rk屏幕相关文档》 驱动板绘制 …

【REST2SQL】14 基于角色的数据权限设计与实现

【REST2SQL】01RDB关系型数据库REST初设计 【REST2SQL】02 GO连接Oracle数据库 【REST2SQL】03 GO读取JSON文件 【REST2SQL】04 REST2SQL第一版Oracle版实现 【REST2SQL】05 GO 操作 达梦 数据库 【REST2SQL】06 GO 跨包接口重构代码 【REST2SQL】07 GO 操作 Mysql 数据库 【RE…

QT状态机10-QKeyEventTransition和QMouseEventTransition的使用

1、QMouseEventTransition的使用 首先明白 QMouseEventTransition 继承自 QEventTransition类。 关于QEventTransition类的使用,可参考 QT状态机9-QEventTransition和QSignalTransition的使用 回顾 QT状态机9-QEventTransition和QSignalTransition的使用 中的状态切换代码,如…

C++动态内存区域划分、new、delete关键字、泛型编程、函数模版、类模版

目录 一、C/C中程序的内存区域划分 为什么会存在内存区域划分&#xff1f; 二、new关键字 1、内置类型的new/delete使用方法&#xff1a; 2、new和delete的本质 3、常见面试题——malloc/free和new/delete的区别 三、模版 1、泛型编程 2、函数模版 &#xff08;1&…

【C语言】6.C语言VS实用调试技巧(2)

文章目录 6.调试举例17.调试举例28.调试举例3&#xff1a;数组9.编程常⻅错误归类9.1 编译型错误9.2 链接型错误9.3 运⾏时错误 – 6.调试举例1 求 1!2!3!4!…10! 的和。 int main() {int n 0;int i 0;int ret 1;int sum 0;for (n 1; n < 3; n) {for (i 1; i < …

LBSS138LT1G 丝印J1 SOT-23 N沟道 50V/200mA 贴片MOSFET

LBSS138LT1G的应用领域广泛&#xff0c;主要因为它是一种N沟道金属氧化物半导体场效应晶体管&#xff08;MOSFET&#xff09;&#xff0c;具有低电荷、快速开关速度和高阻断特性。以下是一些典型的应用领域&#xff1a; 1. 消费电子产品&#xff1a;LBSS138LT1G常用于电视、音响…

四川景源畅信:如何更好的为抖音小店做引流?

在数字化营销的浪潮中&#xff0c;抖音小店作为新兴的电商形态&#xff0c;正以其独特的社交属性和流量优势吸引着众多商家的目光。如何为抖音小店引流&#xff0c;成为许多店主心中的疑问。本文将深入探讨有效提升店铺流量的策略&#xff0c;助你在抖音平台上快速崛起。 一、内…

【漏洞复现】Secnet-智能路由系统 actpt_5g.data信息泄露

0x01 产品简介 Secnet安网智能AC管理系统是广州安网通信技术有限公司(简称“安网通信”)的无线AP管理系统 0x02 漏洞描述 Secnet智能路由系统 acipt 5g.data 接口存在信息泄露漏洞&#xff0c;未经身份验证的远程攻击者可以利用此漏洞获取系统账户名密码等重要凭据&#xff…