|
@@ -0,0 +1,281 @@
|
|
|
+<template>
|
|
|
+ <hc-dialog
|
|
|
+ v-model="isShow" is-table widths="1200px" title="选择地图" @close="cancel"
|
|
|
+ >
|
|
|
+ <div class="amap-box">
|
|
|
+ <el-input id="keyword" v-model="tipInput" clearable placeholder="关键词搜索" />
|
|
|
+ <div id="custom-amap" />
|
|
|
+ <div id="my-panel" />
|
|
|
+ <div v-if="address" class="info-list">
|
|
|
+ <div class="info-item">已选择地点:{{ address }}</div>
|
|
|
+ <div class="info-item">地点经纬度:{{ point }}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <template #footer>
|
|
|
+ <el-button hc-btn type="primary" @click="save">确定</el-button>
|
|
|
+ </template>
|
|
|
+ </hc-dialog>
|
|
|
+</template>
|
|
|
+
|
|
|
+ <script setup>
|
|
|
+ import { onUnmounted, ref, watch } from 'vue'
|
|
|
+ import AMapLoader from '@amap/amap-jsapi-loader'
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ const props = defineProps({
|
|
|
+ defaultAddress: {
|
|
|
+ type: String,
|
|
|
+ default: '',
|
|
|
+ },
|
|
|
+ defaultPoint: {
|
|
|
+ type: Array,
|
|
|
+ default:[],
|
|
|
+ },
|
|
|
+ isShow: {
|
|
|
+ type: Boolean,
|
|
|
+ default: false,
|
|
|
+ },
|
|
|
+ })
|
|
|
+ const emit = defineEmits(['finish', 'close'])
|
|
|
+ const map = ref(null) // 地图对象
|
|
|
+ const address = ref('') // 地址
|
|
|
+ const point = ref([]) // 地址对应的经纬度信息
|
|
|
+
|
|
|
+ const marker = ref('') // 地图标记
|
|
|
+ const geocoder = ref('') // 地址解析(正向)
|
|
|
+
|
|
|
+ const tipInput = ref(props.defaultAddress) // 检索关键字
|
|
|
+ const autoComplete = ref(null)
|
|
|
+ const placeSearch = ref(null)
|
|
|
+
|
|
|
+ const isShow = defineModel('modelValue', {
|
|
|
+ default: false,
|
|
|
+})
|
|
|
+ window._AMapSecurityConfig = {
|
|
|
+ securityJsCode: 'dfd9c521e218fb29772123a488e68c80', //申请key时的安全密钥
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+watch(() => props.defaultAddress, (data) => {
|
|
|
+ tipInput.value = data
|
|
|
+}, { immediate: true, deep: true })
|
|
|
+//监听显示
|
|
|
+watch(isShow, (val) => {
|
|
|
+ if (val) {
|
|
|
+ initMap()
|
|
|
+ }
|
|
|
+})
|
|
|
+
|
|
|
+ // 初始化地图页面
|
|
|
+ const initMap = () => {
|
|
|
+ AMapLoader.load({
|
|
|
+ key: 'dfd9c521e218fb29772123a488e68c80', // 申请好的Web端开发者Key,首次调用 load 时必填
|
|
|
+ version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
|
|
|
+ plugins: [
|
|
|
+ 'AMap.ToolBar',
|
|
|
+ 'AMap.Scale',
|
|
|
+ 'AMap.HawkEye',
|
|
|
+ 'AMap.MapType',
|
|
|
+ 'AMap.Geolocation',
|
|
|
+ 'AMap.AutoComplete',
|
|
|
+ 'AMap.PlaceSearch',
|
|
|
+ 'AMap.Geocoder',
|
|
|
+ ], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
|
|
|
+ })
|
|
|
+ .then((AMap) => {
|
|
|
+ const tempCenter = props.defaultPoint[0]
|
|
|
+ ? props.defaultPoint
|
|
|
+ : [118.784136, 32.041806]
|
|
|
+ map.value = new AMap.Map('custom-amap', {
|
|
|
+ // 设置地图容器id
|
|
|
+ viewMode: '2D', // 是否为3D地图模式
|
|
|
+ zoom: 12, // 初始化地图级别
|
|
|
+ showLabel: true, // 是否展示地图文字和 POI 信息。
|
|
|
+ resizeEnable: true,
|
|
|
+ center: tempCenter, // 初始化地图中心点位置
|
|
|
+ })
|
|
|
+ // 如果父组件传入了有效值 回显一个icon
|
|
|
+ if (props.defaultPoint.length > 0) {
|
|
|
+ address.value = props.defaultAddress
|
|
|
+ point.value = props.defaultPoint
|
|
|
+ addMarker()
|
|
|
+ }
|
|
|
+ // 地图点击事件
|
|
|
+ map.value.on('click', clickMapHandler)
|
|
|
+
|
|
|
+ // 引入高德地图的空间绑定使用
|
|
|
+ map.value.addControl(new AMap.Scale())
|
|
|
+ map.value.addControl(new AMap.ToolBar())
|
|
|
+ map.value.addControl(new AMap.HawkEye())
|
|
|
+ map.value.addControl(new AMap.MapType())
|
|
|
+ map.value.addControl(new AMap.Geolocation())
|
|
|
+
|
|
|
+ // 搜索框自动完成类
|
|
|
+ autoComplete.value = new AMap.AutoComplete({
|
|
|
+ input: 'keyword', // input 为绑定输入提示功能的input的DOM ID
|
|
|
+ })
|
|
|
+ // 构造地点查询类
|
|
|
+ placeSearch.value = new AMap.PlaceSearch({
|
|
|
+ map: map.value,
|
|
|
+ panel: 'my-panel', //结果列表将在此容器中进行展示。
|
|
|
+ autoFitView: true, //是否自动调整地图视野使绘制的 Marker 点都处于视口的可见范围
|
|
|
+ pageSize: 5, //单页显示结果条数
|
|
|
+ pageIndex: 1, //页码
|
|
|
+ })
|
|
|
+ // 当选中某条搜索记录时触发
|
|
|
+ autoComplete.value.on('select', selectHandler)
|
|
|
+ // poi覆盖物点击事件
|
|
|
+ placeSearch.value.on('markerClick', clickMarkerHandler)
|
|
|
+
|
|
|
+
|
|
|
+ })
|
|
|
+ .catch((e) => {
|
|
|
+ console.log(e)
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ const clickMapHandler = (e) => {
|
|
|
+ const lng = e.lnglat.lng
|
|
|
+ const lat = e.lnglat.lat
|
|
|
+ point.value = [lng, lat]
|
|
|
+ // 增加点标记
|
|
|
+ addMarker()
|
|
|
+ // 获取地址
|
|
|
+ getAddress()
|
|
|
+ }
|
|
|
+
|
|
|
+ // 增加点标记
|
|
|
+ const addMarker = () => {
|
|
|
+
|
|
|
+ // 清除其他icon
|
|
|
+ if (marker.value) {
|
|
|
+ marker.value.setMap(null)
|
|
|
+ marker.value = null
|
|
|
+ }
|
|
|
+ // 重新渲染icon
|
|
|
+ marker.value = new AMap.Marker({
|
|
|
+ position: point.value, // icon经纬度
|
|
|
+ offset: new AMap.Pixel(-13, -30), // icon中心点的偏移量
|
|
|
+ icon: new AMap.Icon({
|
|
|
+ image:
|
|
|
+ '//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png',
|
|
|
+ size: new AMap.Size(30, 40), // 图标大小
|
|
|
+ imageSize: new AMap.Size(30, 40),
|
|
|
+ }),
|
|
|
+ })
|
|
|
+ marker.value.setMap(map.value) // 设置icon
|
|
|
+ }
|
|
|
+
|
|
|
+ // 将经纬度转换为地址
|
|
|
+ const getAddress = () => {
|
|
|
+ // 获取地址,这里通过高德 SDK 完成。
|
|
|
+ geocoder.value = new AMap.Geocoder()
|
|
|
+ // 调用逆解析方法, 个人开发者调用量上限5000(次/日)
|
|
|
+ geocoder.value.getAddress(point.value, (status, result) => {
|
|
|
+ if (status === 'complete' && result.info === 'OK') {
|
|
|
+ if (result && result.regeocode) {
|
|
|
+ address.value = result.regeocode.formattedAddress
|
|
|
+ tipInput.value = result.regeocode.formattedAddress
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ // 当选中某条记录时会触发
|
|
|
+ const selectHandler = (e) => {
|
|
|
+
|
|
|
+ placeSearch.value.setCity(e.poi.adcode)
|
|
|
+ // placeSearch.value.search(e.poi.name) // 关键字查询查询
|
|
|
+ //在回调函数中使用插件功能
|
|
|
+ placeSearch.value.search(e.poi.name, function (status, result) {
|
|
|
+
|
|
|
+ const panelElement = document.getElementById('my-panel')
|
|
|
+ panelElement.addEventListener('click', function (event) {
|
|
|
+ // 判断点击的目标是否是搜索结果项
|
|
|
+ const clickedItem = event.target.closest('.poibox')
|
|
|
+ if (clickedItem) {
|
|
|
+ let index = clickedItem.getAttribute('data-idx')
|
|
|
+ const poi = result.poiList.pois[index] // 获取对应索引的POI(兴趣点)信息
|
|
|
+
|
|
|
+ // 这里你可以执行相关操作,比如在地图上标记点击的点,或显示详细信息
|
|
|
+ console.log('点击的 POI 信息:', poi)
|
|
|
+ tipInput.value = poi.name
|
|
|
+ address.value = poi.name
|
|
|
+ point.value = [poi.location.lng, poi.location.lat]
|
|
|
+ map.value.setCenter(poi.location) // 跳转到点击的地点
|
|
|
+ // 如果需要,还可以在地图上添加 Marker 或显示信息窗口等
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ // 点击poi覆盖物事件
|
|
|
+ const clickMarkerHandler = (e) => {
|
|
|
+ point.value = [e.data.location.lng, e.data.location.lat]
|
|
|
+ getAddress()
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ const cancel = () => {
|
|
|
+ emit('close')
|
|
|
+ }
|
|
|
+ const save = () => {
|
|
|
+ emit('finish', tipInput.value)
|
|
|
+ }
|
|
|
+ onUnmounted(() => {
|
|
|
+ map.value && map.value.destroy()
|
|
|
+ })
|
|
|
+ </script>
|
|
|
+
|
|
|
+ <style lang="scss" scoped>
|
|
|
+ #my-panel{
|
|
|
+ position: absolute;
|
|
|
+ top: 10px;
|
|
|
+ right: 10px;
|
|
|
+ z-index: 99;
|
|
|
+ width: 400px !important;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+}
|
|
|
+ .amap-box {
|
|
|
+ padding: 5px 0 0;
|
|
|
+ #custom-amap {
|
|
|
+ width: 100%;
|
|
|
+ height: 600px;
|
|
|
+ margin-top: 10px;
|
|
|
+ border: 1px solid #ccc;
|
|
|
+ }
|
|
|
+
|
|
|
+ .input-with {
|
|
|
+ width: 580px;
|
|
|
+ z-index: 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ .address {
|
|
|
+ color: #373737;
|
|
|
+ }
|
|
|
+ .info-list {
|
|
|
+ padding: 5px 5px 0;
|
|
|
+ line-height: 24px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ </style>
|
|
|
+
|
|
|
+ <style lang="scss">
|
|
|
+ .select-map-dialog {
|
|
|
+ .el-dialog__body {
|
|
|
+ padding-top: 3px;
|
|
|
+ padding-bottom: 3px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .amap-sug-result {
|
|
|
+ z-index: 2024;
|
|
|
+ }
|
|
|
+ </style>
|
|
|
+
|