Vue3使用高德地图、搜索、地图选点、以及省市区三级联动

1、准备工作

需要在 高德开发平台 申请自己的 key密钥
在这里插入图片描述
这里的 Key 名称大家可以随意填写

在这里插入图片描述
申请完之后我们得到 key密钥
在这里插入图片描述

vue中使用需要安装**@amap/amap-jsapi-loader --save** 官方文档

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

2、代码实现

首先我们需要三个文件,一个 index.vue 一个用来存放省市区的 index.js 文件
一个 map.vue 地图组件

index.vue 代码
<template>
    <el-form :model="form" ref="formRef" class="box-from" label-width="95px" label-position="right">
        <el-form-item label="省市区">
            <el-select v-model="form.province" style="width: 180px;" placeholder="请选择省份" clearable @change="provinceChange"
                @clear="provinceClear">
                <el-option v-for="item in province" :key="item.code" :label="item.value" :value="item.value" />
            </el-select>
            <el-select v-model="form.city" style="width: 180px; margin-left: 5px;" placeholder="请选择市" clearable
                @change="cityChange" :disabled="form.province === ''" @clear="cityClear">
                <el-option v-for="item in city" :key="item.code" :label="item.value" :value="item.value" />
            </el-select>
            <el-select v-model="form.area" style="width: 180px; margin-left: 5px;" placeholder="请选择区" clearable
                :disabled="form.city === ''">
                <el-option v-for="item in area" :key="item.code" :label="item.value" :value="item.value" />
            </el-select>
        </el-form-item>
        <el-form-item label="详细地址">
            <el-input style="width: 500px;" type="textarea" v-model="form.address" placeholder="请输入详细地址"
                clearable></el-input>
            <el-button @click="addressMap" style="margin-left: 5px;">地图跳转</el-button>
        </el-form-item>
        <el-form-item label="地图选择">
            <Map :addressClick="addressClick" ref="mapRef"></Map>
        </el-form-item>
    </el-form>
</template>

<script setup lang="ts">
import { reactive, ref, toRefs, onMounted } from 'vue';
import { provinceData } from './index'

const state = reactive({
    // 表单
    province: provinceData,
    city: [] as any,
    area: [] as any,
    form: {
        province: '',
        city: '',
        area: '',
        address: ''
    },
})

const { form, province, city, area } = toRefs(state)

const mapRef = ref('') as any

onMounted(() => {
	// 这里传后台获取的经纬度
    mapRef.value.fixed(100.179253, 27.096143)
})

// 省份
function provinceChange(value: any) {
    state.province.forEach(item => {
        if (item.value === value) {
            state.city = item.children
        }
    })
}

// 市
function cityChange(value: any) {
    state.province.forEach(item => {
        if (item.value === state.form.province) {
            item.children.forEach(text => {
                if (text.value === value) {
                    state.area = text.children
                }
            })
        }
    })
}

// 省清空
function provinceClear() {
    state.form.city = ""
    state.form.area = ""
}

// 市清空
function cityClear() {
    state.form.area = ""
}

// 详细地址跳转地图
function addressMap() {
    mapRef.value.toGetCoordinate(state.form.address)
}


// 地图选位置
// 把获取的信息同步到三级联动
function addressClick(item: any, lng: any, lat: any) {
    if (item.regeocode.addressComponent.city === '') {
        state.form.city = item.regeocode.addressComponent.province
    } else {
        state.form.city = item.regeocode.addressComponent.city
    }
    state.form.province = item.regeocode.addressComponent.province
    state.form.area = item.regeocode.addressComponent.district
    state.form.address = item.regeocode.formattedAddress
    state.province.forEach(item => {
        if (item.value === state.form.province) {
            state.city = item.children
            item.children.forEach(text => {
                if (text.value === state.form.city) {
                    state.area = text.children
                }
            })
        }
    })
}
</script>

<style lang="scss" scoped></style>
map.vue 代码
<template>
    <div style="width: 100%;">
        <div id="container" class="map"></div>
        <div class="search-box">
            <el-select v-model="address" clearable placeholder="请输入关键词" style="width: 400px;" :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>
        </div>
    </div>
</template>

<script setup>
import { reactive, ref, toRefs, onMounted, nextTick, defineProps } from 'vue';
import AMapLoader from "@amap/amap-jsapi-loader";
const props = defineProps({
    addressClick: Function,
})
onMounted(() => {
    window._AMapSecurityConfig = {
        securityJsCode: '这里放key的安全密钥',
    }
    initMap()
})

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",
        version: "2.0",
        plugins: ["AMap.ToolBar", "AMap.ControlBar", 'AMap.AutoComplete', 'AMap.PlaceSearch', 'AMap.Geocoder', 'AMap.Marker'],
    }).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
        })

        state.autoComplete = new AMap.AutoComplete({ city: '全国' });

        state.map.on('click', (e) => { // 点击地图事件
            if (!e && !e.lnglat) {
                return
            }
            state.form.lng = e.lnglat.lng
            state.form.lat = e.lnglat.lat
            removeMarker() // 先删除地图上标记点
            setMapMarker() // 在添加新的标记点
        })
        state.map.addControl(toolBar);   // 添加右上角的放大缩小
        state.map.addControl(controlBar);   // 添加右上角的放大缩小
    }).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) // 返回位置信息以及经纬度
        }
    })
}

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.lng
            state.form.lat = result.geocodes[0].location.lat
            state.form.address = result.geocodes[0].formattedAddress
        }
    })
    nextTick(function () {
        removeMarker()
        setMapMarker()
    })
}

function fixed(lng, lat) {
    initMap([lng, lat])
    state.form.lng = lng
    state.form.lat = lat
}


// 暴露方法
defineExpose({
    fixed,
    toGetCoordinate
});
</script>



<style scoped lang="scss">
.map {
    width: 100%;
    height: 400px;
}

.search-box {
    position: absolute;
    z-index: 9;
    top: 20px;
    left: 20px;

    ::v-deep(.el-select) {
        width: 320px;
        border-radius: 50px;
        overflow: hidden;

        .el-input__wrapper {
            border-radius: 50px;
        }
    }
}
</style>
index.js 代码

这里我以文件的形式上传了,大家直接下载即可 省市区三级联动index.js文件

效果展示
在这里插入图片描述

补充

因为高德地图的搜索每天有限制,可能导致地图上面的搜索无法使用
但是
可以在详细地址那里填写地址信息点击后面按钮跳转地图 (注意:既然是详细地址建议跳转时添加上省市区)

替换自己的key和密钥可以直接使用,如有问题可以私信。

如果对你有帮助麻烦点个赞咯~

  • 10
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
根据提供的引用内容,我无法找到关于Vue3使用高德地图可视化的具体信息。但是,我可以为您提供一些关于Vue高德地图的基本信息。 Vue是一种流行的JavaScript框架,用于构建用户界面。它具有简单易用的语法和强大的功能,可以帮助开发人员快速构建交互式的Web应用程序。 高德地图是一种基于Web的地图服务,提供了丰富的地图数据和功能,包括地图显示、地理编码、路径规划、导航等。它可以用于在Web应用程序中显示地图,并与其他功能进行集成。 要在Vue使用高德地图可视化,您可以按照以下步骤进行操作: 1. 在Vue项目中安装高德地图JavaScript API库。您可以通过在HTML文件中添加以下代码来实现: ```html <script src="https://webapi.amap.com/maps?v=2.0&key=您的高德地图API密钥"></script> ``` 请注意,您需要将"您的高德地图API密钥"替换为您自己的API密钥。 2. 创建一个Vue组件,用于显示地图。可以在组件的模板中添加一个具有唯一ID的div元素,用于容纳地图。例如: ```html <template> <div id="mapContainer"></div> </template> ``` 3. 在Vue组件的脚本部分,使用Vue的生命周期钩子函数(例如created)来初始化地图。您可以使用高德地图JavaScript API来创建地图实例,并将其绑定到div元素上。例如: ```javascript <script> export default { created() { const map = new AMap.Map('mapContainer', { // 地图配置选项 }); } } </script> ``` 请注意,这只是一个简单的示例,您可以根据自己的需求进行配置和定制。 这是一个基本的示例,演示了如何在Vue使用高德地图可视化。您可以根据自己的需求进一步扩展和定制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值