当前位置: 首页 > news >正文

高德地图2.0 绘制、编辑多边形覆盖物(电子围栏)

在这里插入图片描述

1. 安装

npm i @amap/amap-jsapi-loader --save

移步:官方文档

2. map组件封装

<script lang="ts" setup>
import AMapLoader from '@amap/amap-jsapi-loader'
import { onMounted, ref } from 'vue'
import { propTypes } from '@/utils/propTypes'defineOptions({ name: 'Map' })const props = defineProps({bindId: propTypes.string.def('mapContainer'),modelValue: propTypes.array.def([]),title: propTypes.string.def(''),width: propTypes.string.def('100%'),height: propTypes.string.def('600px'),polygonPaths: propTypes.array.def([]), // 回显多边形路径 得是<nubmer[]>类型,不然无法编辑districtCode: propTypes.string.def('140101') // 行政区划代码
})watch(() => props.districtCode,(newVal, oldVal) => {if (newVal !== oldVal) {drawBounds()}}
)window._AMapSecurityConfig = {securityJsCode: '4e6ca573a89ac3176f29813d3fcc895e'
}
const mouseTool = ref()
const mapRef = ref(null)
const overlays = ref<object[]>([])
const polyEditor = ref<any>()
const district = ref<any>()
const AMapObj = ref<any>()// 新建
const createPolygon = () => {polyEditor.value.close()polyEditor.value.setTarget()polyEditor.value.open()
}const emits = defineEmits(['update:modelValue'])
//获取
const getPolygon = () => {let overlays = mapRef.value?.getAllOverlays('polygon')let polygonPaths = overlays.map((overlay: any) => overlay.getPath())polygonPaths.shift() // 去掉第一个多边形console.log('🚀 ~ getPolygon ~ polygonPaths:', polygonPaths)const paths: object[] = []polygonPaths.forEach((item: any) => {const pathItem = item.map((cItem: any) => {const lnglat = `${cItem.lng},${cItem.lat}`return lnglat})paths.push(pathItem)})emits('update:modelValue', paths)
}defineExpose({ getPolygon })//清除绘制的多边形
const clearPolygon = () => {try {closeEditor()mapRef.value?.clearMap()drawBounds()} catch (e) {console.log(e)}
}// 开启编辑
const openEditor = () => {if (polyEditor.value) {polyEditor.value.open()}
}// 关闭编辑
const closeEditor = () => {if (polyEditor.value) {polyEditor.value.close()}
}//加载行政区划插件
const drawBounds = () => {if (!district.value) {//实例化DistrictSearchvar opts = {subdistrict: 0, //获取边界不需要返回下级行政区extensions: 'all', //返回行政区边界坐标组等具体信息level: 'district' //查询行政级别为 市}district.value = new AMap.DistrictSearch(opts)}//行政区查询district.value.setLevel('district')var keyword = props.districtCodeif (keyword === '') {console.warn('行政区划不能为空')return}let polygon = nulldistrict.value.search(keyword, function (status, result) {if (polygon) {mapRef.value?.remove(polygon) //清除上次结果polygon = null}if (!result || !result.districtList || !result.districtList[0]) {console.warn('请正确填写名称或更新其他名称')return}var bounds = result.districtList[0].boundariesif (bounds) {//生成行政区划polygonfor (var i = 0; i < bounds.length; i += 1) {//构造MultiPolygon的pathbounds[i] = [bounds[i]]}polygon = new AMap.Polygon({path: bounds,strokeColor: '#F56C6C',strokeWeight: 4,fillOpacity: 0.1,fillColor: '#F56C6C',strokeStyle: 'dashed',strokeDasharray: [12, 3],zIndex: 0})mapRef.value?.add(polygon)mapRef.value?.setFitView(polygon) //视口自适应}})
}// 编辑事件处理
const editPolygon = () => {polyEditor.value.on('add', function (data) {var polygon = data.targetpolyEditor.value.addAdsorbPolygons(polygon)polygon.on('dblclick', (e) => {polyEditor.value.setTarget(polygon)polyEditor.value.open()})})// polyEditor.value.on('adjust', function (data) {//   console.log('🚀 ~ polyEditor-adjust', data)// })// polyEditor.value.on('addnode', function (data) {//   console.log('🚀 ~ polyEditor-addnode', data)// })// polyEditor.value.on('end', function (data) {//   console.log('🚀 ~ polyEditor-end', data)// })
}// 回显多边形
const showPolygon = (polygonArr: any) => {// const polygonArr = [[116.368904, 39.913423], [116.382122, 39.901176],[116.387271, 39.912501],[116.398258, 39.9046]]const polygon = new AMap.Polygon({path: polygonArr,strokeColor: '#1791fc',strokeOpacity: 0.9,strokeWeight: 4,fillColor: '#1791fc',fillOpacity: 0.3,strokeStyle: 'solid', //solid, 线样式还支持 'dashed',strokeDasharray: [12, 4], // strokeStyle是dashed时有效zIndex: 16})// polygon.on('click', (e) => {//   console.log('🚀 ~ polygon.on ~ e:', e)// })mapRef.value?.add(polygon)polyEditor.value.addAdsorbPolygons([polygon])polygon.on('dblclick', () => {polyEditor.value.setTarget(polygon)polyEditor.value.open()})mapRef.value?.setFitView(polygon) //视口自适应
}// defineExpose({ showPolygon })// 加载高德地图
const loader = () => {AMapLoader.load({key: '947ec8e0b6869f9ef9fc6badda641a06',version: '2.0', // 使用合适的版本plugins: ['AMap.Scale', 'AMap.MouseTool', 'AMap.PolygonEditor', 'AMap.DistrictSearch']}).then((AMap) => {AMapObj.value = AMap// 初始化地图mapRef.value = new AMap.Map(props.bindId, {zoom: 15,center: [116.397428, 39.90923] // 设置地图中心点})// 加载行政区划插件drawBounds()// 编辑事件处理polyEditor.value = new AMap.PolygonEditor(mapRef.value)editPolygon()// 回显保存的多边形props.polygonPaths.forEach((item: any) => {showPolygon(item)})mapRef.value?.on('click', (e) => {console.log('🚀 ~ mapRef.value.on ~ e:', e)})}).catch((error) => {console.error('加载高德地图失败', error)})
}onMounted(() => {loader()
})
</script><template><div class="mb-14px"><el-button @click="createPolygon" type="primary">新建</el-button><!-- <el-button @click="openEditor" type="primary">编辑</el-button> --><el-button @click="closeEditor" type="primary">关闭编辑</el-button><el-button @click="clearPolygon" type="danger" plain>清空</el-button><!-- <el-button @click="getPolygon" type="primary">获取</el-button> --></div><div :id="props.bindId" :style="{ width: width, height: height }"></div>
</template>

3. 使用组件

<template><el-drawer v-model="drawer2" :direction="direction" size="75%" :show-close="false"><template #header><div><divclass="w-full flex items-center justify-between border-b border-b-[var(--el-border-color)] border-b-solid pb14px"><div class="font-size-4">服务区域</div><el-button type="primary" @click="close" size="small" circle><Icon icon="ep:close-bold" :size="16" @click="cancelClick" /></el-button></div></div></template><template #default><div class="flex items-center justify-center pb30px font-size-15px color-#666">起始地: {{ curRow.startDistrictName }}<el-icon class="mx-20px"><Switch /></el-icon>目的地: {{ curRow.endDistrictName }}</div><div class="flex justify-center"><div class="mx-10px w-50%"><div><MapbindId="startMap"v-model:modelValue="startPolygonPaths"v-if="drawer2"ref="StartMapRef":polygonPaths="startDetailPaths":districtCode="curRow.startDistrictCode"/></div></div><div class="mx-10px w-50%"><div><MapbindId="endMap"v-model:modelValue="endPolygonPaths"v-if="drawer2"ref="EndMapRef":polygonPaths="endDetailPaths":districtCode="curRow.endDistrictCode"/></div></div></div></template><template #footer><div style="flex: auto"><el-button @click="cancelClick">取消</el-button><el-button type="primary" @click="confirmClick">确认</el-button></div></template></el-drawer>
</template><script lang="ts" setup>
import { Switch } from '@element-plus/icons-vue'
import { ref, nextTick } from 'vue'
import { Map } from '@/components/Map/index'
import { getLinesServiceAreaList, saveLinesServiceArea } from '@/api/routeManage/routeList/index.ts'
const drawer2 = ref(false)
const direction = ref('rtl')
const curRow = ref<object>({})
const dcistrictCode = ref('')
const startPolygonPaths = ref([])
const endPolygonPaths = ref([])
const startDetailPaths = ref([])
const endDetailPaths = ref([])
const message = useMessage()// 打开推窗
const open = async (row) => {curRow.value = rowawait getDetail()drawer2.value = true
}
defineExpose({ open })const StartMapRef = ref(null)
const EndMapRef = ref(null)
const getDetail = async () => {const params = {...}try {const data = await getLinesServiceAreaList(params)...startDetailPaths.value =[[112.557711,37.731122],[112.625256,37.734871],[112.558896,37.680496],[112.558896,37.680496]]endDetailPaths.value = [[112.676067,36.378644],[112.79624,36.385946],[112.732752,36.29097],[112.732752,36.29097]]} finally {}
}// 获取起点数据
const getStartData = () => {const linesServiceAreaList = startPolygonPaths.value.map((item) => {if (item) {return { areaType: 1, pointList: item }}})return linesServiceAreaList || []
}// 获取终点数据
const getEndData = () => {const linesServiceAreaList = endPolygonPaths.value.map((item) => {if (item) {return { areaType: 1, pointList: item }}})return linesServiceAreaList || []
}const confirmClick = async () => {await StartMapRef.value?.getPolygon()await EndMapRef.value?.getPolygon()const params = {areaList: [...getStartData(), ...getEndData()]}try {await saveLinesServiceArea(params)message.success('保存成功')} finally {drawer2.value = false}
}function cancelClick() {drawer2.value = false
}
</script>

相关文章:

高德地图2.0 绘制、编辑多边形覆盖物(电子围栏)

1. 安装 npm i amap/amap-jsapi-loader --save移步&#xff1a;官方文档 2. map组件封装 <script lang"ts" setup> import AMapLoader from amap/amap-jsapi-loader import { onMounted, ref } from vue import { propTypes } from /utils/propTypesdefineO…...

MySQL底层为什么选择用B+树作为索引

首先&#xff0c;我们来想想为什么这么多数据结构&#xff0c;为什么要用树这种数据结构&#xff1f; 众多的数据结构在逻辑层面可分为&#xff1a;线性结构 和 非线性结构。 线性结构有&#xff1a;数组、链表&#xff0c;基于它们衍生出的有哈希表&#xff08;哈希表也称散…...

MATLAB系列05:自定义函数

MATLAB系列05&#xff1a;自定义函数 5. 自定义函数5.1 MATLAB函数简介5.2 在MATLAB中传递变量&#xff1a;按值传递机制5.3 选择性参数5.4 用全局内存分享数据5.5 在函数两次调用之间本地数据的存储5.6 函数的函数(function functions)5.7 子函数和私有函数5.8 总结 5. 自定义…...

C++速通LeetCode简单第20题-多数元素

方法一&#xff1a;暴力解法&#xff0c;放multiset中排序&#xff0c;然后依次count统计&#xff0c;不满足条件的值erase清除。 class Solution { public:int majorityElement(vector<int>& nums) {int ans 0;multiset<int> s;for(int i 0;i < nums.s…...

回收站永久删除的文件还能恢复吗?教你恢复技巧

在数字时代&#xff0c;电脑是我们工作、学习和娱乐的重要工具。然而&#xff0c;随着我们对电脑的频繁使用&#xff0c;误删文件的情况也时有发生。当我们在回收站中不小心永久删除了某个重要文件时&#xff0c;内心可能会充满焦虑和疑惑&#xff1a;这些文件还能恢复吗&#…...

Python Web 微服务架构全面解析与实战指南

Python Web 微服务架构全面解析与实战指南 目录 &#x1f3d7;️ 微服务基础概念 微服务架构与单体架构的对比微服务的优点与挑战 &#x1f504; 服务间通信 使用REST、gRPC或消息队列实现服务通信API网关的使用&#xff08;如Kong、Traefik&#xff09; &#x1f50d; 服务…...

SEAFARING靶场漏洞攻略

寻找漏洞 一&#xff0c;我们打开页面 第一个漏洞 xss漏洞 1.在登录页面显示有弹窗 第二个漏洞 sql注入漏洞 1.在输入框的地方输入-1 union select 1,2,3#我们来查看他的回显点 2.查看数据库表名 -1 union select 1,database(),3# 3.查看表名 -1 union select 1,2,group…...

ROS 编程入门的介绍

2.1 创建 ROS 功能包 ROS&#xff08;Robot Operating System&#xff09;是一种开源的机器人软件框架&#xff0c;广泛用于机器人开发中。通过使用 ROS&#xff0c;开发者可以轻松创建和管理机器人应用程序。在本节中&#xff0c;我们将介绍如何创建一个 ROS 功能包并实现一些…...

第十一章 抽象类与接口

一、抽象类和抽象方法 抽象类&#xff1a;使用abstract修饰的类 抽象方法&#xff1a;在类中没有方法体的方法&#xff0c;称为抽象方法&#xff0c;抽象方法用abstract修饰 抽象类中可以没有抽象方法&#xff0c;包含抽象方法的类必是抽象类 如果子类没有实现父类中的全部…...

请问企业的八大金刚系统是哪些?有什么共同点和区别?

我的理解的八大金刚包括&#xff1a;MES、ERP、WMS、OMS、CRM、SCM、SRM、PLM。 这些系统的主要功能及运用领域是哪些方面?他们互相之前有什么区别&#xff1f;选择时哪些是企业可能根据自身需求选择的必选项目或可选项目&#xff1f; 由于某些系统的必选性取决于企业的具体业…...

【入门】配置 Java 应用程序的完整指南

前言&#xff1a; Java 是一种广泛使用的编程语言&#xff0c;具备跨平台的特性&#xff0c;使得其应用程序可以在多种环境中高效运行。本文将介绍如何将 Java 应用程序从开发环境部署到生产环境&#xff0c;确保其能够稳定、稳定地运行运行。 确定运行环境 Java程序可以运行…...

flutter widget 设置GestureDetector点击无效

有可能是被上层的widget挡住了&#xff0c;虽然你看得到这个widget&#xff0c;但是操作不到。使用相对布局Stack要特别注意&#xff0c;这种布局会和Android一样&#xff0c;先写的布局放在下层&#xff0c;后写的&#xff0c;如果范围较大的话&#xff0c;会盖在之前的widget…...

基于SpringBoot的在线教育平台的设计与实现

文未可获取一份本项目的java源码和数据库参考。 选题的背景与意义&#xff1a; 随着互联网时代信息技术的不断发展&#xff0c;线下已经产生了很多IT技术的培训机构&#xff0c;但是价格却十分昂贵并且需要人们持续不断的去具体培训地点学习&#xff0c;因此更需要一个课程优…...

Django_Vue3_ElementUI_Release_004_使用nginx部署

1. nginx安装配置 1.1 下载nginx Download nginx 1.2 测试一下 1.3 进入nginx用命令操作 2. 部署 2.1 前端部署 2.1.1 修改nginx监听配置 …conf/nginx.conf http {... # 这里不进行修改server {listen 8010; # 监听 80 端口server_name 192.168.10.24; # 输入服务器 ip…...

Java抽象类的案例

抽象类的特点总结 不能实例化&#xff1a;抽象类不能直接创建实例。它只能被继承。即&#xff0c;你不能用 new 关键字创建抽象类的对象。 可以包含抽象方法&#xff1a;抽象类可以包含一个或多个抽象方法&#xff08;没有方法体&#xff09;&#xff0c;这些方法必须在子类中…...

运维工程师面试整理-数据库

在运维工程师的面试中,数据库管理和优化是一个非常重要的环节。面试官可能会通过数据库相关的问题来评估你在数据库部署、管理、备份、性能优化以及故障排除方面的能力。以下是关于数据库部分的详细内容,帮助你更好地准备面试。 1. 数据库基础 ● 常见数据库类型 ○ 关系型数…...

comfyui一键抠图工作流:让你告别PS!

前言 本文涉及的工作流和插件&#xff0c;需要的朋友请扫描免费获取哦~ 在当今的数字时代&#xff0c;图像处理已经成为许多行业的日常需求。无论是电商产品展示、广告设计&#xff0c;还是个人照片编辑&#xff0c;去除背景都是一个常见且重要的步骤。 然而&#xff0c;使用…...

【Hot100】LeetCode—4. 寻找两个正序数组的中位数

目录 1- 思路题目识别二分 2- 实现⭐4. 寻找两个正序数组的中位数——题解思路 3- ACM 实现 原题链接&#xff1a;4. 寻找两个正序数组的中位数 1- 思路 题目识别 识别1 &#xff1a;给定两个数组 nums1 和 nums2 &#xff0c;找出数组的中位数 二分 思路 将寻找中位数 —…...

【LLM text2sql】浅看大模型用于text2sql的综述

前言 之前笔者分享了text2sql & LLM & KG的有机结合实现KBQA的问答&#xff0c; 《【LLM & RAG & text2sql】大模型在知识图谱问答上的核心算法详细思路及实践》、 《【开源分享】KBQA核心技术及结合大模型SPARQL查询生成问答实践》。 我们再来看看大模型在te…...

Node js介绍

目录 概要**对Node的认识****Node的概念理解****Node和浏览器区别****Node的架构图** **Node的应用场景****Node的安装****安装Node的LTS版本****Node的版本管理工具nvm(了解)** **Node的输入和输出**Node程序传递参数Node的输出 **Node的全局对象****特殊的全局对象****其他的…...

业务系统对接大模型的基础方案:架构设计与关键步骤

业务系统对接大模型&#xff1a;架构设计与关键步骤 在当今数字化转型的浪潮中&#xff0c;大语言模型&#xff08;LLM&#xff09;已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中&#xff0c;不仅可以优化用户体验&#xff0c;还能为业务决策提供…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩

目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

条件运算符

C中的三目运算符&#xff08;也称条件运算符&#xff0c;英文&#xff1a;ternary operator&#xff09;是一种简洁的条件选择语句&#xff0c;语法如下&#xff1a; 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true&#xff0c;则整个表达式的结果为“表达式1”…...

Golang dig框架与GraphQL的完美结合

将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用&#xff0c;可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器&#xff0c;能够帮助开发者更好地管理复杂的依赖关系&#xff0c;而 GraphQL 则是一种用于 API 的查询语言&#xff0c;能够提…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

OPENCV形态学基础之二腐蚀

一.腐蚀的原理 (图1) 数学表达式&#xff1a;dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一&#xff0c;腐蚀跟膨胀属于反向操作&#xff0c;膨胀是把图像图像变大&#xff0c;而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...

Java后端检查空条件查询

通过抛出运行异常&#xff1a;throw new RuntimeException("请输入查询条件&#xff01;");BranchWarehouseServiceImpl.java // 查询试剂交易&#xff08;入库/出库&#xff09;记录Overridepublic List<BranchWarehouseTransactions> queryForReagent(Branch…...

结构化文件管理实战:实现目录自动创建与归类

手动操作容易因疲劳或疏忽导致命名错误、路径混乱等问题&#xff0c;进而引发后续程序异常。使用工具进行标准化操作&#xff0c;能有效降低出错概率。 需要快速整理大量文件的技术用户而言&#xff0c;这款工具提供了一种轻便高效的解决方案。程序体积仅有 156KB&#xff0c;…...

Android屏幕刷新率与FPS(Frames Per Second) 120hz

Android屏幕刷新率与FPS(Frames Per Second) 120hz 屏幕刷新率是屏幕每秒钟刷新显示内容的次数&#xff0c;单位是赫兹&#xff08;Hz&#xff09;。 60Hz 屏幕&#xff1a;每秒刷新 60 次&#xff0c;每次刷新间隔约 16.67ms 90Hz 屏幕&#xff1a;每秒刷新 90 次&#xff0c;…...

接口 RESTful 中的超媒体:REST 架构的灵魂驱动

在 RESTful 架构中&#xff0c;** 超媒体&#xff08;Hypermedia&#xff09;** 是一个核心概念&#xff0c;它体现了 REST 的 “表述性状态转移&#xff08;Representational State Transfer&#xff09;” 的本质&#xff0c;也是区分 “真 RESTful API” 与 “伪 RESTful AP…...