当前位置: 首页 > 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的全局对象****特殊的全局对象****其他的…...

测试微信模版消息推送

进入“开发接口管理”--“公众平台测试账号”&#xff0c;无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息&#xff1a; 关注测试号&#xff1a;扫二维码关注测试号。 发送模版消息&#xff1a; import requests da…...

全球首个30米分辨率湿地数据集(2000—2022)

数据简介 今天我们分享的数据是全球30米分辨率湿地数据集&#xff0c;包含8种湿地亚类&#xff0c;该数据以0.5X0.5的瓦片存储&#xff0c;我们整理了所有属于中国的瓦片名称与其对应省份&#xff0c;方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

Rust 异步编程

Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...

Ascend NPU上适配Step-Audio模型

1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统&#xff0c;支持多语言对话&#xff08;如 中文&#xff0c;英文&#xff0c;日语&#xff09;&#xff0c;语音情感&#xff08;如 开心&#xff0c;悲伤&#xff09;&#x…...

使用 SymPy 进行向量和矩阵的高级操作

在科学计算和工程领域&#xff0c;向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能&#xff0c;能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作&#xff0c;并通过具体…...

服务器--宝塔命令

一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行&#xff01; sudo su - 1. CentOS 系统&#xff1a; yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...

在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案

这个问题我看其他博主也写了&#xff0c;要么要会员、要么写的乱七八糟。这里我整理一下&#xff0c;把问题说清楚并且给出代码&#xff0c;拿去用就行&#xff0c;照着葫芦画瓢。 问题 在继承QWebEngineView后&#xff0c;重写mousePressEvent或event函数无法捕获鼠标按下事…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)

一、OpenBCI_GUI 项目概述 &#xff08;一&#xff09;项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台&#xff0c;其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言&#xff0c;首次接触 OpenBCI 设备时&#xff0c;往…...