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

news2024/11/16 1:40:40

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:很多博主都把文章设置为关注后才能查看,感觉这样有点恶心。如果我的文章切实能给各位观众老爷们带来帮助,真心求点个关注,再次感谢各位观众老爷们了。

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

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

相关文章

echarts去掉网格线

柱子后面白色的线太丑了&#xff01; 去掉他 x轴平行的线&#xff0c;就写在yAxis下面 yAxis: {type: value,splitLine: {lineStyle: {type: dashed, // 虚线样式color: rgba(255, 255, 255, 0.15) // 虚线颜色}},//去除网格线}, 这个颜色一定要加‘’&#xff0c;不然不生效…

使用python开发的闭运算调试器

使用python开发的开运算调试器 简介效果代码 简介 用来调试闭运算效果的小工具&#xff0c;滑动条可以控制滤波核的大小&#xff0c;用来查看不同滤波核下的闭运算效果。 效果 代码 import sys from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QHBoxLayou…

2024新零售行业多元化用工报告

来源&#xff1a;君润人力 近期历史回顾&#xff1a;

国外客户怀疑我们产品质量要如何应对

经常有外贸小伙伴问我&#xff0c;国外客户怀疑我们的产品质量要如何应对&#xff1f; 这个问题应该算是外贸经常遇到的一个问题&#xff0c;今天就简单来给大家分享几个我认为可以去入手跟客户回复解决的这个问题的点。 首先&#xff0c;我们要知道&#xff0c;不管你做啥产品…

Stable Diffusion入门使用技巧及个人试用实例分享--生成稳定人物及姿势篇

上节我们主要讲解了SD提示词的实践篇及ControlNet常用模型篇&#xff0c;本节主要想给大家分享一下如何在不自己单独训练lora的情况下尽量稳定的控制生成的人物的脸及姿势。欢迎阅读。 一、如何稳定生成相同的人物&#xff08;脸部&#xff09; 1、瞎编名字法&#xff1a; d…

第八篇 Asciidoc 输出 All In One HTML 解决图片无法显示问题

问题:我的图片显示不出来了 小明使用 Asciidoc 来记笔记,他将笔记输出为 HTML 文件。小丽向小明借笔记。小明将 Asciidoc 笔记输出为 HTML文件,并拷贝给了小丽。 但是,小丽发现,图片都显示不出来了。 小丽:小明,你给我的笔记,图片都显示不出来啊。 小明:是我给你的…

H2-FDetector模型解析

文章目录 1. H2FDetector_layer 类2. RelationAware 类3. MultiRelationH2FDetectorLayer 类4. H2FDetector 类 这个实现包括三个主要部分&#xff1a;H2FDetector_layer、MultiRelationH2FDetectorLayer 和 H2FDetector。每个部分都有其独特的功能和职责。下面是这些组件的详细…

thinkphp8扩展think-swoole4.0-事件监听代码

首先服务端配置监听 swoole.php <?phpreturn [http > [enable > true,host > 0.0.0.0,port > 8000,worker_num > swoole_cpu_num(),options > [],],websocket > [enable > true,handler > \think\swo…

【达梦数据库】搭建 DM->mysql dblink

DM->mysql dblink 1安装mysql odbc rpm -ivh mysql-connector-odbc-5.3.14-1.el7.x86_64.rpm2mysql创建远程用户与远程数据库 mysql> show databases; ------------------------- | Database | ------------------------- | information_schema | …

行测练习题

、、 【任意直角三角形&#xff0c;斜边的中点到三个顶点的距离相等。】 因此无人机的投影点一定为直角三角形斜边中点&#xff0c;之后根据勾股定理可以求得高度为500. 、、

桌椅3D模型素材从哪下载比较好?

对于室内设计师而言&#xff0c;经常需要用到桌椅3D模型来完成自己的设计方案&#xff0c;那么从哪里能下载高质量的桌椅3D模型素材呢? 1、建e网&#xff1a;建e网的3D模型库不仅数量庞大&#xff0c;而且质量上乘。模型制作精细&#xff0c;纹理清晰&#xff0c;可以直接用于…

【Open AI】GPT-4o深夜发布:视觉、听觉跨越式升级

北京时间5月14日1点整&#xff0c;OpenAI 召开了首场春季发布会&#xff0c;CTO Mira Murati 在台上和团队用短短不到30分钟的时间&#xff0c;揭开了最新旗舰模型 GPT-4o 的神秘面纱&#xff0c;以及基于 GPT-4o 的 ChatGPT&#xff0c;均为免费使用。 本文内容来自OpenAI网站…

vue-cropper裁剪图片 vue

效果图 1.配置环境 npm install vue-cropper 2.代码 <template><div class"cropper-content"><div class"cropper-box"><div class"cropper"><vue-cropper ref"cropper" :img"option.img" :…

5 个免费使用 GPT-4o 的方法

5 个免费使用 GPT-4o 的方法 虽然距离 OpenAI 发布 GPT-4o 已过去一天&#xff0c;我仍然对 GPT-4o 感到震撼。Demo 中语音助手功能实在是太令人惊叹了——它咯咯的笑声、准确的语气感叹和歌唱方式让 Siri 和 Google Assistant 显得相形见绌。 虽然备受期待的语音助手功能还要…

Elasticsearch:向量相似度技术和评分

作者&#xff1a;来自 Elastic Valentin Crettaz 当需要搜索自由文本并且 CtrlF / CmdF 不再有效时&#xff0c;使用词法搜索引擎通常是你想到的下一个合理选择。 词汇搜索引擎擅长分析要搜索的文本并将其标记为可在搜索时匹配的术语&#xff0c;但在理解和理解被索引和搜索的…

Acrel-2000L/A 绝缘监测系统设备 对多个绝缘检测仪进行统一数据管理

一、产品简介 Acrel-2000L/A 绝缘监测系统设备适用于 1kV 及以下低压配电系统。该设备可以集中采集监测显示绝缘监测仪的数据&#xff0c;实现最多 8 个绝缘监测仪的数据&#xff0c;并且实时记录告警信息和曲线查询。匹配的绝缘监测仪可以是 AIM-T300、AIM-T500 和 AIM-T500L。…

python 两种colorbar 最大最小和分类的绘制

1 colorbar 按照自定义的最值绘制 归一化方法使用Normalize(vmin0, vmax40.0) import numpy as np import matplotlib as mpl import matplotlib.pyplot as plt import matplotlib.cm as cm import matplotlib.colors as mcolors from matplotlib import rcParams from matplot…

【全开源】国际版JAVA同城服务美容美发到店服务上门服务系统源码支持Android+IOS+H5

国际版同城服务美容美发到店与上门服务系统&#xff1a;一站式打造美丽新体验 随着人们生活水平的提高和审美观念的升级&#xff0c;美容美发服务已成为人们日常生活中不可或缺的一部分。为了满足全球消费者的多样化需求&#xff0c;我们推出了“国际版同城服务美容美发到店与…

基于单片机的光照检测系统—光敏电阻

基于单片机的光照检测系统 &#xff08;仿真&#xff0b;程序&#xff0b;原理图&#xff0b;设计报告&#xff09; 功能介绍 具体功能&#xff1a; 1.光敏电阻实时采集环境光照值&#xff1b; 2.采用ADC0804将模拟值转换为数字量&#xff1b; 3.四位数码管显示当前的光照…

(gpt4o教程)gpt-4o如何开启和使用呢?

我发现&#xff0c;很多人反馈他的官网里没有gpt-4o的选项&#xff0c;下面介绍一下怎么查看是否使用了gpt-4o模型。 一、使用方法 1. 官网网站直接使用 2. 通过Open API申请接口使用 3. 通过LLM基准测试竞技场体验 还有其他方法&#xff0c;就不一一举例了。可以先看看上…