vue3+Ts+Ant Design Vue +天地图组件封装

​🌈个人主页:前端青山
🔖人终将被年少不可得之物困其一生

依旧青山,本期给大家带来Vue3+Ts+AntDesign-Vue组件+天地图组件的封装

示例图

首先,在index.html引入天地图资源,vue3选择v4版本

    <script src="http://api.tianditu.gov.cn/api?v=4.0&tk=你的秘钥" type="text/javascript"></script>
  1. 使用<BasicModal>组件作为模态框基础样式,并通过@register@ok@cancel等事件来注册、提交和取消选择点位操作。
  2. 组件内部使用天地图(Tianditu)进行地图展示和操作,包括初始化地图、点击地图获取坐标、根据地址搜索坐标等。
  3. 组件提供了一个搜索框,用户可以输入地址,通过点击搜索按钮来搜索对应的坐标,并在地图上标记。
  4. 组件可以接收初始的经纬度信息(通过initialLongitudeinitialLatitude两个props传递),并在地图上标记该位置。
  5. 组件内部使用了一些变量和函数来保存和操作地图、标记等信息,例如mapInstancecurrentMakerlongitudelatitude等。
  6. 组件提供了successcancel两个自定义事件,用于在选择点位成功或取消时通知父组件。

地图弹框示例代码

<template><div style="width: 100%" @click="show"><slot></slot><!-- 弹框组件 --><BasicModalwidth="1000px"@register="registerModal"@ok="submit"@cancel="handleCancel"destroy-on-close:title="'请选择点位'"><div class="mb-2"><Input id="tipinput" v-model:value="searchValue" :placeholder="'请填写详细地址'"/><a-button type="primary" @click="search">搜索</a-button></div><!-- 使用天地图容器 --><div id="mapDiv" ref="wrapRef" style="width: 100%; height: 500px"><div id="Tip" v-if="showCurrent">当前坐标:{{longitude}}-{{latitude}}</div></div></BasicModal></div>
</template><script setup lang="ts">import { onMounted, ref ,nextTick,toRefs } from 'vue';import { BasicModal, useModal } from '/@/components/Modal';import { Input, message } from 'ant-design-vue';import GpsIcon from '/@/assets/images/gps.png';const emits = defineEmits(['success', 'cancel']);// 天地图相关数据绑定const mapInstance = ref(null as any);// 搜索区域内容const searchValue = ref('');// 变量保存Maker实例const currentMaker = ref(null as any);// 经度const longitude = ref('');// 纬度const latitude = ref('');// 判断当前坐标是否显示const showCurrent = ref(false);
// 在setup函数顶部声明缓存位置信息的ref
const lastSelectedLocation = ref({ longitude: '', latitude: '' });// 地理编码服务相关的变量let geocoder: any = null;const siteInfo = ref({longitude: '',address: '',latitude: ''});const props = defineProps({// 添加初始经纬度propsinitialLongitude: {type: String,default: '',},initialLatitude: {type: String,default: '',},// ... 其他props不变 ...
});
const { initialLongitude, initialLatitude } = toRefs(props);const [registerModal, { closeModal, openModal }] = useModal();declare global {interface Window {T: any;TMAP_VECTOR_MAP: any;}}
var T = window.T;// 初始化天地图<style scoped>#mapDiv {width: 100%;height: 100vh;}.mb-2 {display: flex;}#Tip {position: absolute;color: #424B5A;font-weight: bold;font-size: 14px;bottom: 40px;left: 18px;z-index: 999;}
</style>

这段代码是Vue组件中的一部分,主要功能是实现了天地图的初始化和地图功能的绑定。

  • 首先,通过ref函数定义了一些变量,用于保存地图实例、搜索区域内容、Maker实例、经度、纬度、当前坐标是否显示等。

  • 然后,通过defineProps定义了组件接收的props,包括初始经度和纬度等。

  • 使用useModal函数定义了一个模态框的实例。

  • 在全局声明了一个Window接口,增加了TTMAP_VECTOR_MAP属性。

  • 最后,定义了一个initTiandituMap异步函数,用于初始化天地图。该函数会创建一个天地图实例,并根据传入的初始经纬度进行定位,并添加一个标记到地图上。

    • 首先,根据initialLongitudeinitialLatitude的值进行地图中心点的设置和缩放级别设定,并添加一个新的标记到地图上。

    • 如果没有传入初始经纬度,则将地图中心点设置为默认值(97.53662, 35.36499)。

  const initTiandituMap = async () => {var map: any = null;var T = window.T;map = new T.Map("mapDiv");map.setMapType(window.TMAP_VECTOR_MAP);// 根据传入的初始经纬度进行定位if (initialLongitude.value && initialLatitude.value) {map.centerAndZoom(new T.LngLat(Number(initialLongitude.value) ,Number(initialLatitude.value) ), 7);const newMarker = createNewMarker(new T.LngLat(initialLongitude.value, initialLatitude.value));map.addOverLay(newMarker);currentMaker.value = newMarker;} else {map.centerAndZoom(new T.LngLat(97.53662, 35.36499), 7);}mapInstance.value = map;map.addEventListener('click', (val: any) => {handleMapClick(val);});
};const handleMapClick = (val: any) => { if (currentMaker.value) {console.log(currentMaker.value,'有之前点位信息');mapInstance.value.removeOverLay(currentMaker.value);}siteInfo.value.longitude = val.lnglat.lng;siteInfo.value.latitude = val.lnglat.lat;longitude.value = val.lnglat.lng;latitude.value = val.lnglat.lat;showCurrent.value = true;const icon = new T.Icon({iconUrl: GpsIcon,iconSize: new T.Point(30, 30),iconAnchor: new T.Point(15, 15),});const newMarker = new T.Marker(val.lnglat);newMarker.setIcon(icon);mapInstance.value.addOverLay(newMarker);currentMaker.value = newMarker;};onMounted(() => {geocoder = new window.T.Geocoder();initTiandituMap();});function show() {openModal();// 确保在模态框打开且DOM更新后初始化或重新初始化地图nextTick(() => {initTiandituMap(); // 直接调用 initTiandituMapsearchValue.value= '';longitude.value = '';latitude.value = '';showCurrent.value = false; // 默认不显示当前坐标});}const search =  () => {console.log(searchValue.value,'search');const map:any = mapInstance.value;if (!geocoder || !searchValue.value) return;// 清除地图上覆盖物if (currentMaker.value) {mapInstance.value.removeOverLay(currentMaker.value);}geocoder.getPoint(searchValue.value, function(result) {if (result) {if (result.status == 0) {map.panTo(result.getLocationPoint(), 16);const newMarker = createNewMarker(result.getLocationPoint());map.addOverLay(newMarker);map.clearOverLays();updateCoordinates(newMarker.getPosition());} else {message.error(`搜索失败: ${result.getMsg()}`);}}});};function createNewMarker(position: any) {const icon = new T.Icon({iconUrl: GpsIcon,iconSize: new T.Point(30, 30),iconAnchor: new T.Point(15, 15),});const marker = new T.Marker(position);marker.setIcon(icon);return marker;}function updateCoordinates(position: any) {longitude.value = position.lng;latitude.value = position.lat;showCurrent.value = true;siteInfo.value.longitude = position.lng;siteInfo.value.latitude = position.lat;}// 在submit函数中更新缓存的位置信息
function submit() {lastSelectedLocation.value = { longitude: siteInfo.value.longitude, latitude: siteInfo.value.latitude };emits('success', {latitude: siteInfo.value.latitude.toString(),longitude: siteInfo.value.longitude.toString(),});closeModal();
}function handleCancel() {emits('cancel');closeModal();}
</script>
  1. 首先,将地图实例赋值给mapInstance,然后给地图添加点击事件监听器,当点击地图时,会调用handleMapClick函数。
  2. handleMapClick函数根据点击的坐标点信息,移除之前添加的标记(如果有),更新当前位置信息,并添加一个新的标记到地图上。
  3. onMounted生命周期函数用于在组件挂载后执行初始化地图的操作。
  4. show函数用于打开模态框并初始化或重新初始化地图。
  5. search函数用于根据输入的搜索值进行地点搜索,清除之前添加的标记,将搜索结果标记在地图上,并更新当前位置信息。
  6. createNewMarker函数用于创建一个新的标记,并设置标记的样式。
  7. updateCoordinates函数用于更新当前位置信息。
  8. submit函数用于在提交表单时更新缓存的位置信息,并触发success事件。
  9. handleCancel函数用于在取消操作时触发cancel事件,并关闭模态框。

表单封装

把我们封装好的地图弹框引入给于事件传参

表单组件示例代码

<div><FormItemRest><MapModal v-model:value="location" @success="handleSuccess":initial-longitude="location.longitude":initial-latitude="location.latitude"><div calss="map" style="display:flex"><div><a-inputreadonly:disabled="disabled":placeholder="placeholder"v-model:value="location.longitude":size="size":bordered="bordered"@blur="emit('blur')"style="min-width: 150px"> </a-input></div><div style="margin:5px 10px">-</div><div> <a-inputreadonly:disabled="disabled":placeholder="placeholder"v-model:value="location.latitude":size="size":bordered="bordered"@blur="emit('blur')"style="min-width: 150px"></a-input></div> <div style="margin:5px 10px;"><Icon icon='mdi:map-marker-radius-outline' /></div></div></MapModal></FormItemRest></div><style scoped>
.map{display: flex;
}
</style>

这段代码是Vue的一个模板,用于渲染一个包含地图模态框和两个输入框的表单项。其中:

  • <FormItemRest> 是一个表单项容器组件;
  • <MapModal> 是一个地图模态框组件,通过 v-model:value 绑定到 location 属性,表示地图选择的地理位置,@success 事件在选择成功时触发,:initial-longitude 和 :initial-latitude 分别绑定到 location.longitude 和 location.latitude,表示地图的初始经度和纬度;
  • <a-input> 是一个输入框组件,通过 v-model:value 绑定到 location.longitude 和 location.latitude,表示经度和纬度的值,readonly 和 :disabled 表示输入框为只读且不可用状态,:placeholder 表示占位符,:size 和 :bordered 分别表示输入框的大小和边框样式,@blur 表示输入框失去焦点时触发的事件;
  • <Icon> 是一个图标组件,显示一个地图标记的图标。

 

<script>import { Form } from 'ant-design-vue';import { MapModal } from '/@/components/Map/index';import { watch, ref, inject } from 'vue';import { Icon } from '/@/components/Icon';import { camelCaseString } from '/@/utils/event/design';// 用于包裹弹窗的form组件 因为一个FormItem 只能收集一个表单组件  所以弹窗的form 必须排除const FormItemRest = Form.ItemRest;const props = defineProps({value: String,prefix: String,suffix: String,placeholder: String,readonly: Boolean,disabled: Boolean,size: String,bordered: {type: Boolean,default: true,},latitude: String,latiAndLong: String,index: Number,mainKey: String,longitude:String,});const location:any = ref<{ latitude: string; longitude: string }>({ latitude: '', longitude: '' });//对象形式接收经度维度const emit = defineEmits(['update:value', 'change', 'blur']);const formModel = inject<any>('formModel', null); // 注入表单数据const isCustomForm = inject<boolean>('isCustomForm', false);watch(() => props.value,() => {location.value.longitude = props.longitude,location.value.latitude = props.valueconsole.log('props.value', props);if (!props.value) {//预览页面 重置location.value = { latitude: '', longitude: '' };}},{immediate: true,},);function handleSuccess(v) {location.value = { latitude: v.latitude, longitude: v.longitude };console.log('MAP handleSuccess ', v);changeFieldData(v);emit('update:value', location.value.latitude,location.value.longitude);emit('change',location.value.latitude,location.value.longitude);}function changeFieldData(v) {if (!formModel) return;if (props.latitude) {const latitudeField: any = isCustomForm ? props.latitude : camelCaseString(props.latitude);if (props.mainKey && props.index !== undefined && props.index !== null) {formModel[props.mainKey][props.index][latitudeField] = v.latitude;} else {formModel[latitudeField] = v.latitude;}}if (props.latiAndLong) {const latiAndLong: any = isCustomForm? props.latiAndLong: camelCaseString(props.latiAndLong);if (props.mainKey && props.index != undefined && props.index !== null) {formModel[props.mainKey][props.index][latiAndLong] = v.lnglat.join(',');} else {formModel[latiAndLong] = v.lnglat.join(',');}}}
</script>
  • 引入Ant Design Vue的Form组件和自定义的MapModal组件。
  • 引入Vue 3的watchrefinject等函数。
  • 定义组件的props,包括输入框的值、前缀、后缀、占位符、只读、禁用、大小、是否带边框、经度、纬度等。
  • 使用ref定义一个location的响应式对象,用来保存经度和纬度数据。
  • 使用defineEmits定义组件可以发出的事件,包括update:valuechangeblur
  • 使用inject来注入表单数据的formModel和是否为自定义表单的isCustomForm
  • 使用watch来监听props.value的变化,并更新location的值。如果props.value为空,则重置location
  • 定义handleSuccess函数,用来处理地图弹窗成功获取到数据的情况。将数据更新到location,并调用changeFieldData函数更新表单数据,最后通过emit发出事件。

最后我们在页面进行组件引入即可

创作不易,点个关注不迷路~~~ 

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

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

相关文章

【Redis】NoSQL之Redis的配置和优化

关系型数据库与非关系型数据库 关系型数据库 关系型数据库是一个结构化的数据库&#xff0c;创建在关系型模型&#xff08;二维表&#xff09;的基础上&#xff1b;一般面向于记录&#xff1b; SQL语句(标准数据查询语句)就是一种基于关系型数据库的语言&#xff0c;用于执行…

安装 windows 版 dash —— zeal

1、下载安装 下载地址&#xff1a;Download Zeal 选择 Protable 版 直接使用 zeal 下载文档比较慢甚至失败&#xff0c;可以设置代理&#xff0c;也可以使用下面两种方式。 2、手动下载 docset 文档后导入 这种方法不能够选择文档的版本 &#xff08;1&#xff09;在 http://…

达梦数据库的V$DM_INI和V$PARAMETER系统视图

V$DM_INI和V$PARAMETER是达梦数据库中两个常用的系统视图&#xff0c;用于查看数据库的配置参数。这两个视图的主要区别在于它们展示参数的来源和用途。 V$DM_INI V$DM_INI视图主要用于展示数据库启动时加载的初始化参数信息。这些信息通常来自于数据库的初始化参数文件&…

自动驾驶中的传感器融合算法:卡尔曼滤波器和扩展卡尔曼滤波器

自动驾驶中的传感器融合算法&#xff1a;卡尔曼滤波器和扩展卡尔曼滤波器 附赠自动驾驶学习资料和量产经验&#xff1a;链接 介绍&#xff1a; 追踪静止和移动的目标是自动驾驶技术领域最为需要的核心技术之一。来源于多种传感器的信号&#xff0c;包括摄像头&#xff0c;雷达…

VSCode输入花括号{}}会多一个解决方案

打开设置 搜索Closing Brackets 选择BeforeWhitespace 选完后重启下VSCode即可

ddres( ) 组站星双差方程和设计矩阵

1 ddres( )参数介绍 rtklib中进行的单频解算 双差观测值&#xff0c;单差的模糊度 单频点双差 DD (double-differenced) phase/code residuals ------------------------------ x 模糊度 P 方差-协方差阵 sat 共识卫星列表 ns 共识卫星数量 y…

模型优化和调整(2)

接模型优化和调整&#xff08;1&#xff09; 调整反向传播 梯度消失和梯度爆炸 梯度消失和梯度爆炸都和计算出来的“delta”有关。理想的delta应该是逐渐减小的。如果delta一直太小&#xff0c;则会导致下降太慢&#xff0c;甚至对于权重没有改变&#xff0c;此时形成了梯度…

深入C语言内存:数据在内存中的存储

一、数据类型 1. unsigned&#xff1a;无符号数类型 当一个数是无符号类型时&#xff0c;那么其最高位的1或0&#xff0c;和其它位一样&#xff0c;用来表示该数的大小。 2.signed&#xff1a;有符号数类型 当一个数是有符号类型时&#xff0c;最高数称为“符号位”。符号位为1…

绝地求生:第29赛季第1轮更新公告

正式服维护日期 ※ 下列时间可能会视维护情况而变化。 北京时间4月9日上午8:00 – 下午4:30 地图轮换 ※ 地图轮换将于北京时间每周三上午10点进行。 日期 正式服 – 普通比赛 可自主选择地图的地区 - 亚洲、东南亚 可自主选择地图的地区 – 韩国/日本、KAKAO 随机选择地…

【随笔】Git 基础篇 -- 分支与合并 git merge(九)

&#x1f48c; 所属专栏&#xff1a;【Git】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#x1f496; 欢迎大…

重生奇迹MU玛雅宝石功能

玛雅宝石是重生奇迹mu游戏中的重要合成材料&#xff0c;玩家可以使用玛雅宝石合成属性果实、副本门票等道具。不过玛雅宝石的获取不易&#xff0c;所以使用起来一个都不能浪费。今天就给大家分享一些玛雅宝石使用效益最大化的经验。 获取与使用 在游戏中&#xff0c;玛雅宝石…

有人吐槽:低代码平台自带可视化报表,你定制化设计有啥市场?

类似这种评论&#xff0c;我见过的太多了。photoshop触手可及&#xff0c;设计高手又有几人呢&#xff1f; 工具毕竟就是工具&#xff0c;能不能用好&#xff0c;完全在于个体。 实不相瞒&#xff0c;我们接过N多可视化报表的美化业务&#xff0c;这就好比天猫有默认的店铺模…

JAVA面试八股文之Redis相关

Redis相关 Redis6.0为什么要用多线程&#xff1f;在Redis中存一个list集合怎么实现排序&#xff1f;Redis的5大基本类型的底层原理&#xff1f;缓存穿透&#xff1f;缓存击穿&#xff1f;缓存雪崩&#xff1f;redis做为缓存怎么保持和mysql数据进行同步&#xff1f;&#xff08…

Spring声明式事务(Spring学习笔记十三)

不推荐使用编程式事务 在Spring-dao.xml中配置声明式事务 <!--配置声明式事务 --><!--获得transactionManager然后把他丢给他的构造器 constructor-arg --><bean id"transactionManager" class"org.springframework.jdbc.datasource.Data…

ENSP 防火墙配置IPSecVPN点到多点

建议关闭物理机系统防火墙 应用场景 总部与分支机构通信&#xff1a;企业总部可以与遍布不同地理位置的分支机构建立安全的通信通道。远程用户访问&#xff1a;远程用户可以通过IPSec VPN隧道安全地访问公司内部网络资源&#xff0c;就像他们直接连接到公司网络一样。数据共享和…

【MySQL学习】MySQL的慢查询日志和错误日志

꒰˃͈꒵˂͈꒱ write in front ꒰˃͈꒵˂͈꒱ ʕ̯•͡˔•̯᷅ʔ大家好&#xff0c;我是xiaoxie.希望你看完之后,有不足之处请多多谅解&#xff0c;让我们一起共同进步૮₍❀ᴗ͈ . ᴗ͈ აxiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客 本文由xiaoxieʕ̯•͡˔•̯᷅ʔ 原创 CSDN …

鸿蒙OS开发实战:【自动化测试框架】使用指南

概述 为支撑HarmonyOS操作系统的自动化测试活动开展&#xff0c;我们提供了支持JS/TS语言的单元及UI测试框架&#xff0c;支持开发者针对应用接口进行单元测试&#xff0c;并且可基于UI操作进行UI自动化脚本的编写。 本指南重点介绍自动化测试框架的主要功能&#xff0c;同时…

【Spring Security】2.实现最简单的身份验证

文章目录 一、找到官网的身份认证&#xff08;authentication&#xff09;示例代码二、实现最简单的身份验证1、创建Spring Boot项目2、创建IndexController3、创建index.html4、启动项目测试Controller 三、{/logout}的作用四、页面样式无法加载的问题 一、找到官网的身份认证…

二建考试搜题软件哪个好?分享8个可以搜答案的软件 #知识分享#笔记#学习方法

积极参加社团活动和实践项目&#xff0c;可以帮助大学生拓宽人脉圈和锻炼实际操作能力。 1.白鸽搜题 这是个微信公众号 多语言查询支持&#xff0c;满足国际用户需求。全球通用&#xff0c;无障碍搜题。 下方附上一些测试的试题及答案 1、等渗性脱水时&#xff0c;体液变化…

禅道任务如何删除

背景 利用禅道任务&#xff0c;来统计项目投入工时&#xff0c;但由于录入错误&#xff0c;导致工时写错&#xff0c;想修改但工时只会增加。 问题复现 先复现一下问题&#xff1a; 举例&#xff1a;2/6号工时之前由于操作失误&#xff0c;写成8小时&#xff0c;且任务状态为…