Vue3 + Element-Plus 对接高德地图实现搜索提示选址、点击地图选址、自我定位功能(最新)

Vue3 + Element-Plus 对接高德地图实现搜索提示选址、点击地图选址、自我定位功能(最新)

  • 1、效果展示
  • 2、实现代码
    • 2.1 GaoDeMap.vue
    • 2.2 SystemDialog.vue
    • 2.3 UnusedList.vue.vue

1、效果展示

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2、实现代码

2.1 GaoDeMap.vue


<template><div style="width: 100%;"><div class="search-box"><el-select v-model="address" clearable placeholder="请输入位置关键词" style="width: 240px;" :remote-method="remoteMethod"filterable remote @change="currentSelect" class="one-text" size="default"><el-option v-for="(item, index) in areaList" :key="index" :label="item.district + item.name":value="item.district + item.name"><span>{{ item.district }}</span> <span>{{ item.name }}</span></el-option></el-select><el-button type="success" v-if="addressGet" class="address">{{ addressGet.split(",")[0] }}</el-button></div><div id="container" class="map"></div></div>
</template><script setup>
import { reactive, ref, toRefs, onMounted, nextTick, defineProps, defineEmits } from 'vue';
import AMapLoader from "@amap/amap-jsapi-loader";
// 定义 props 和 emits
const emits = defineEmits(['address']);
const props = defineProps({addressClick: Function,
})
onMounted(() => {window._AMapSecurityConfig = {securityJsCode: '你的安全密钥', // https://console.amap.com/dev/key/app   绑定的服务为 Web端}initMap()
})
const addressGet = ref("")const state = reactive({map: null,placeSearch: null,autoComplete: null,marker: null,form: {address: '',lng: '',lat: '',},areaList: [],address: ''
})const { areaList, address } = toRefs(state)
function initMap(arr) {AMapLoader.load({key: "安全密钥左边的key的值",	// https://console.amap.com/dev/key/app   绑定的服务为 Web端version: "2.0",plugins: ["AMap.ToolBar", "AMap.ControlBar", 'AMap.AutoComplete', 'AMap.PlaceSearch', 'AMap.Geocoder', 'AMap.Marker', 'AMap.Geolocation'],}).then((AMap) => {state.map = new AMap.Map('container', {viewMode: "3D",  //  是否为3D地图模式zoom: 15,center: arr,resizeEnable: true});// 地图放大缩小插件let toolBar = new AMap.ToolBar({position: {top: '120px',right: '51px'}})// 3D地图插件let controlBar = new AMap.ControlBar({position: {top: '20px',right: '20px',},});state.geoCoder = new AMap.Geocoder({city: '010', //城市设为北京,默认:“全国”radius: 1000 //范围,默认:500});// 正向地理编码state.geocoder = new AMap.Geocoder({city: state.address})// 定位let geolocation = new AMap.Geolocation({enableHighAccuracy: true, // 是否使用高精度定位,默认:truetimeout: 10000, // 超过10秒后停止定位,默认:5sposition: {top: '300px',right: '30px',}, // 定位按钮的停靠位置buttonOffset: new AMap.Pixel(10, 20), // 定位按钮与设置的停靠位置的偏移量,默认:Pixel(10, 20)zoomToAccuracy: true, // 定位成功后是否自动调整地图视野到定位点});// 监听定位按钮的点击事件geolocation.on('complete', (result) => {console.log('定位成功:', result);// 处理定位成功的逻辑console.log(result.position.lng, result.position.lat);// 使用高德地图 JavaScript API 的坐标转换服务将 WGS84 坐标转换为 GCJ02 坐标AMap.convertFrom([result.position.lng, result.position.lat], 'gps', (status, result) => {if (status === 'complete' && result.locations.length > 0) {const gcj02Lng = result.locations[0].lng;const gcj02Lat = result.locations[0].lat;// 解析定位结果为中文地址let lnglat = [gcj02Lng, gcj02Lat];console.log(gcj02Lng, gcj02Lat);state.geoCoder.getAddress(lnglat, (status, addressResult) => {if (status === 'complete' && addressResult.regeocode) {let formattedAddress = addressResult.regeocode.formattedAddress;console.log('解析后的地址:', formattedAddress);// 在这里处理解析后的地址addressGet.value = formattedAddress;state.address = formattedAddress;// 返回给父组件的值emits("address", `${formattedAddress},${gcj02Lng},${gcj02Lat}`);}});// 这里可以继续处理转换后的坐标数据,例如显示标记点等} else {console.error('Coordinate conversion failed.');}});});geolocation.on('error', (error) => {console.error('定位失败:', error);// 处理定位失败的逻辑});state.autoComplete = new AMap.AutoComplete({ city: '全国' });state.map.setDefaultCursor("pointer"); // 使用CSS默认样式定义地图上的鼠标样式state.map.on('click', (e) => { // 点击地图事件if (!e && !e.lnglat) {return}state.form.lng = e.lnglat.lngstate.form.lat = e.lnglat.latremoveMarker() // 先删除地图上标记点setMapMarker() // 在添加新的标记点})state.map.addControl(toolBar);   // 添加右上角的放大缩小state.map.addControl(controlBar);   // 添加右上角的放大缩小state.map.addControl(geolocation);   // 添加右上角的放大缩小// 监听定位成功事件}).catch((e) => {console.error(e);  //加载错误提示}).finally(() => {removeMarker()setMapMarker()})}function setMapMarker() {if (state.form.lng == '' && state.form.lat == '') {return}state.map.setFitView()state.marker = new AMap.Marker({map: state.map,position: [state.form.lng, state.form.lat],})toGetAddress()state.map.setFitView()state.map.add(state.marker)
}function removeMarker() {if (state.marker) {state.map.remove(state.marker)}
}function toGetAddress() {let lnglat = [state.form.lng, state.form.lat]state.geoCoder.getAddress(lnglat, (status, result) => {if (status === 'complete' && result.regeocode) {props.addressClick(result, state.form.lng, state.form.lat) // 返回位置信息以及经纬度addressGet.value = `${result.regeocode.formattedAddress},${state.form.lng},${state.form.lat}`}})
}function remoteMethod(query) {if (query !== '') {setTimeout(() => {state.autoComplete.search(query, (status, result) => {state.areaList = result.tips})}, 500)} else {state.areaList = []}
}
function currentSelect(val) {if (!val) {return}toGetCoordinate(val)
}function toGetCoordinate(address) {state.geocoder.getLocation(address, function (status, result) {if (status === 'complete' && result.info === 'OK') {initMap([result.geocodes[0].location.lng, result.geocodes[0].location.lat])state.form.lng = result.geocodes[0].location.lngstate.form.lat = result.geocodes[0].location.latstate.form.address = `${result.geocodes[0].formattedAddress}`// 返回给父组件的值emits("address", `${result.geocodes[0].formattedAddress},${result.geocodes[0].location.lng},${result.geocodes[0].location.lat}`);}})nextTick(function () {removeMarker()setMapMarker()})
}function fixed(lng, lat) {initMap([lng, lat])state.form.lng = lngstate.form.lat = lat
}// 暴露方法
defineExpose({fixed,toGetCoordinate
});
</script><style scoped lang="scss">
.map {width: 100%;height: 400px;padding-top: 20px;
}#container {margin-top: 20px;border-radius: 5px;
}.search-box {display: flex;}.address {margin-left: 20px;
}
</style>

2.2 SystemDialog.vue

<!--* @Date: 2024-03-25 16:55:53* @LastEditors: zhong* @LastEditTime: 2024-04-18 11:21:23* @FilePath: \app-admin\src\components\SystemDialog\SystemDialog.vue
-->
<template><div><el-dialog :model-value="props.visible" :title="props.title" :width="props.width + 'px'":height="props.height + 'px'" :before-close="onClose" :close-on-click-modal="false"><!-- 内容显示区 --><div class="container" :style="{ height: height + 'px' }"><slot name="content"></slot></div><template #footer><div class="dialog-footer"><el-button @click="onClose" type="danger">取消</el-button><el-button type="success" @click="onConfirm">确认</el-button></div></template></el-dialog></div>
</template><script setup lang="ts">
// 定义弹窗数据类型
interface dialogProps {title: string,visible: boolean,width: number,height: number
}// 接收父组件传递的参数
const props = withDefaults(defineProps<dialogProps>(), {title: "新增",visible: false,width: 630,height: 280
})
// 注册事件
const emit = defineEmits(["onClose", "onConfirm"])// 关闭事件
const onClose = () => {emit("onClose");
}
// 提交事件
const onConfirm = () => {emit("onConfirm");
}
</script><style lang="scss" scoped>
.container {overflow-x: inherit;overflow-y: auto;
}:deep(.el-dialog) {padding: 0;border-top-left-radius: 7px !important;border-top-right-radius: 7px !important;.el-dialog__header {margin-right: 0px;padding-top: 10px;border-top-left-radius: 7px !important;border-top-right-radius: 7px !important;background-color: #009688 !important;.el-dialog__title {padding: 16px;color: #FFF;font-size: 16px;font-weight: 600;}}.el-dialog__headerbtn {.el-dialog__close {color: #FFF;}}.el-dialog__body {padding: 10px;}.el-dialog__footer {border-top: 1px solid #e8eaec !important;padding: 10px;}
}
</style>

2.3 UnusedList.vue.vue

<template><SystemDialog :title="name" :visible="mapOpen" :height="400" :width="800" @on-close="closeAddress" @on-confirm="commitAddress"><template v-slot:content><el-form-item label="宝贝位置"><GaoDeMap :addressClick="addressClick" ref="mapRef" @address="getAddress"></GaoDeMap></el-form-item></template></SystemDialog>
</template><script setup lang="ts">
import { onMounted, ref } from 'vue';
import SystemDialog from '@/components/SystemDialog/SystemDialog.vue';
import GaoDeMap from '@/components/Map/GaoDeMap.vue'const mapRef = ref('') as any
const name = ref("宝贝位置选取");
const mapOpen = ref(false)const address = ref("");
const getAddress = (data: string) => {if (data != "") {address.value = data;addGoodParm.address = data;}
}// 提交地图地址
const commitAddress = () => {// 提交地图地址addGoodParm.address = address.value;// 关闭地图mapOpen.value = false;console.log(address, addGoodParm.address);}// 关闭地图
const closeAddress = () => {addGoodParm.address = "";address.value = "";// 关闭地图mapOpen.value = false;
}
// 地图选位置
function addressClick(item: { regeocode: { addressComponent: { city: string; province: string; district: string; }; formattedAddress: string; }; }, lng: number, lat: number) {address.value = `${item.regeocode.formattedAddress}, ${lng}, ${lat}`;
}onMounted(() => {// 这里传后台获取的经纬度mapRef.value.fixed(100.179253, 27.096143)
})
</script>

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

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

相关文章

书生·浦语 大模型(学习笔记-5)XTuner 微调 LLM:1.8B、多模态、Agent

一&#xff1a;两种微调 增量与训练和指令微调的区别 二、数据的一生 原始数据转换为标准格式数据 添加对话模板&#xff0c;直接调用即可&#xff0c;会拼接 三、微调方案 三种加载对比 四、XTuner 五、8GB 显存玩转 LLM 五、InternLM2 1.8B模型&#xff08;相关知识&#x…

GAN 生成对抗神经网络

GAN 文章目录 GANGAN的结构GAN的目标函数GAN的训练GAN的优势和不足优势不足 GAN的结构 GAN的设计灵感来源于博弈论中的零和博弈&#xff08;Zero-sum Game&#xff09;&#xff0c;在零和博弈中&#xff0c;参与双方的收益是完全相反的&#xff0c;一方的收益必然导致另一 方的…

正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-1.3

前言&#xff1a; 本文是根据哔哩哔哩网站上视频“正点原子[第二期]Linux之ARM&#xff08;MX6U&#xff09;裸机篇”的学习笔记&#xff0c;在这里会记录下正点原子Linux ARM MX6ULL 开发板根据配套的哔哩哔哩学习视频所作的实验和笔记内容。本文大量的引用了正点原子哔哔哩网…

初学python记录:力扣2739. 总行驶距离

题目&#xff1a; 卡车有两个油箱。给你两个整数&#xff0c;mainTank 表示主油箱中的燃料&#xff08;以升为单位&#xff09;&#xff0c;additionalTank 表示副油箱中的燃料&#xff08;以升为单位&#xff09;。 该卡车每耗费 1 升燃料都可以行驶 10 km。每当主油箱使用了…

new String和直接赋值的一些问题

分析1 我们先看以下代码&#xff1a; String str1 "abc"; // 在常量池中String str2 new String("abc"); // 在堆上System.out.println(str1 str2)以上结果的输出是什么&#xff1f; 输出&#xff1a;false 前置知识&#xff1a; 在JVM中&#xff0c…

电脑怎么拖动文件到想要的位置?电脑上拖拽没了的文件怎么找回

在日常的办公和学习中&#xff0c;电脑文件拖拽操作是每位用户都不可或缺的技能。然而&#xff0c;有时在拖动文件时&#xff0c;可能会因为误操作或其他原因&#xff0c;导致文件消失或移至未知位置。本文将详细解析如何在电脑上轻松拖动文件到指定位置&#xff0c;并为您提供…

【前端必看】10年资深前端工程师,聊点行业现状与自我突破!

作为一名拥有10年前端开发经验的资深工程师&#xff0c;曾在蚂蚁金服等一线大厂历练&#xff0c;现在则在一家上市公司享受较为宽松的工作节奏。今天&#xff0c;我想和大家聊聊前端开发的就业现状&#xff0c;以及如何在这个竞争激烈的市场中突出重围。 感兴趣的可以看看这个…

GaussDB轻量化运维管理工具介绍

前言 本期课程将从管理平台的架构出发&#xff0c;结合平台的实例管理、实例升级、容灾管理和监控告警的功能和操作介绍&#xff0c;全面覆盖日常运维操作&#xff0c;带您理解并熟练运用GaussDB运维平台完成运维工作。 一、GaussDB 运维管理平台简介 开放生态层 友好Web界面…

OWASP发布十大开源软件安全风险及应对指南

​ 最近爆发的XZ后门事件&#xff0c;尽管未酿成Log4j那样的灾难性后果&#xff0c;但它再次敲响了警钟&#xff1a;软件供应链严重依赖开源软件&#xff0c;导致现代数字生态系统极其脆弱。面对层出不穷的安全漏洞&#xff0c;我们需要关注开源软件 (OSS)风险 &#xff0c;改进…

通过代理IP实现匿名网上冲浪

目录 前言 一、代理IP的原理 1.1 什么是代理IP&#xff1f; 1.2 代理IP的工作原理 二、使用代理IP实现匿名网上冲浪的代码示例 三、如何获取代理IP 四、使用代理IP的注意事项 五、总结 前言 在互联网上冲浪是我们生活中常见的一项活动&#xff0c;然而&#xff0c;在某…

XiaodiSec day017 Learn Note 小迪安全学习笔记

XiaodiSec day017 Learn Note 小迪安全学习笔记 记录得比较凌乱&#xff0c;不尽详细 day 17 主要内容&#xff1a; php 框架 thinkPHPyiilaravel 使用 fofa 搜索 thinkphp 市面上 thinkphp5 版本较多 url 结构 域名/.php(文件名)/index(目录)/index(函数名)模块名-控…

XL7015输出12V电源设计

描述 XL7015是一款高效、高压降压型DC-DC转换器&#xff0c;固定150KHz开关频率&#xff0c;可提供最高0.8A输出电流能力&#xff0c;低纹波&#xff0c;出色的线性调整率与负载调整率。XL7015内置固定频率振荡器与频率补偿电路&#xff0c;简化了电路设计。PWM控 制 环 路 可 …

Android 组件提供的状态保存(saveInstanceState)与恢复(restoreInstanceState)

在Android的组件Activity中&#xff0c;有这样一对方法: onSaveInstanceeState 和 onRestoreInstanceState 这两对方法&#xff0c;可以让我在Activiy被异常销毁时&#xff0c;保存状态&#xff1b;以及在Activity重建时&#xff0c;恢复状态。 比如&#xff1a;当我们在输入…

只有IP没有域名怎么实现HTTPS访问

只有IP地址没有域名可以实现HTTPS访问&#xff1f;虽然通常情况下SSL证书是与域名关联并颁发的&#xff0c;但确实存在针对IP地址发放的SSL证书。这种类型的证书允许服务器通过HTTPS协议为其公网IP地址提供安全的Web服务。这意味着用户可以直接在浏览器中输入服务器的IP地址&am…

免翻!全球最大免费书库Zlibrary最新镜像,国内可直接访问,赶紧下书

刚刚&#xff0c;“知识大航海”群里&#xff0c;有位群友分享了一个Zlibrary镜像地址&#xff0c;感谢这位群友的热心分享&#xff0c;这个地址国内可以直接访问&#xff01; 在“王不留”GZ号&#xff0c;写“zlib”四个字母&#xff0c;有Zlibrary镜像网址、官方网址&#x…

搜维尔科技:如何选择最佳的xsens动作捕捉设备

xsens介绍 如何选择最佳的xsens动作捕捉设备 选择最佳的 Xsens 动作捕捉设置并不总是像我们希望的那样简单。根据每个人的情况&#xff0c;会有不同的选择、要求和挑战。 这就是我们创建此博客的原因&#xff1a;帮助您做出最适合您的决定。 您已经决定继续使用 Xsens 了吗…

神经网络进阶

⚠申明&#xff1a; 未经许可&#xff0c;禁止以任何形式转载&#xff0c;若要引用&#xff0c;请标注链接地址。 全文共计3077字&#xff0c;阅读大概需要3分钟 &#x1f308;更多学习内容&#xff0c; 欢迎&#x1f44f;关注&#x1f440;【文末】我的个人微信公众号&#xf…

19 使用MapReduce编程统计超市1月商品被购买的次数

首先将1月份的订单数据上传到HDFS上&#xff0c;订单数据格式 ID Goods两个数据字段构成 将订单数据保存在order.txt中&#xff0c;&#xff08;上传前记得启动集群&#xff09;。 打开Idea创建项目 修改pom.xml&#xff0c;添加依赖 <dependencies><dependency>…

微软发布Phi-3 Mini,性能媲美GPT-3.5、Llama-3,可在手机端运行

前言 微软发布了最新版的Phi系列小型语言模型(SLM) - Phi-3。这个系列包括3个不同参数规模的版本&#xff1a;Phi-3 Mini (38亿参数)、Phi-3 Small (70亿参数)和Phi-3 Medium (140亿参数)。 Phi系列模型是微软研究团队开发的小规模参数语言模型。从第一代Phi-1到第二代Phi-2&…

想把MP3音频转换成OGG格式需要什么工具?四种你不知道的音频转换工具在这里

​一&#xff0c;引言 随着数字音乐的发展&#xff0c;音频格式的种类也日益增多。MP3和OGG是其中两种常见的音频格式&#xff0c;它们各有优缺点&#xff0c;适用于不同的场景。有时&#xff0c;我们可能需要将MP3格式的音频转换为OGG格式&#xff0c;以满足特定的需求。本文…