亲宝软件园·资讯

展开

Vue3 高德地图选点

三锤 人气:0

前言

最近在做的管理后台项目中有一个业务场景是添加门店的地址和经纬度,地址可以输入,但经纬度这样处理却不合适,最好是让用户在地图上搜索或者直接点击获取点的经纬度等详细信息。因为我们的app中使用了高德地图,所以管理后台我也选用高德地图来实现上面的业务需求,下面来看一下具体的使用流程吧。

获取地图Key

引入地图 JSAPI

项目中使用了官方推荐的 JSAPI Loader 来加载地图

<script setup>
import AMapLoader from '@amap/amap-jsapi-loader';
window._AMapSecurityConfig = {
  securityJsCode: '你申请的安全密钥',
};
</script>

初始化地图

<script setup>
const map = shallowRef(null);
let AMapObj;
function initMap() {
   AMapLoader.load({
     key: '你申请的Key', 
     version: '2.0',
   }).then(AMap => {
        AMapObj = AMap;
        map.value = new AMap.Map('mapContainer');
      })
}
</script>

地图选点

项目中提供搜索选点和直接点击地图选点两种方法

组件化使用

为了方便一整套逻辑的复用,我将以上流程全部封装到一个组件中,通过 v-model 绑定所选地点的详细信息,方便选择地点之后将信息同步到父组件。

下面贴出组件全部的代码

<template>
<div class="map-wrapper">
    <div id="mapcontainer"></div>
    <div class="search-box">
        <el-autocomplete
            v-model="keyword"
            :fetch-suggestions="handleSearch"
            :trigger-on-focus="false"
            clearable
            placeholder="输入城市+关键字搜索"
            @select="handleSelect"
            style="width: 300px"
        />
        <el-input
            v-model="location.longitude"
            placeholder="点击地图选择经度"
            maxlength="15"
            readonly
            style="width: 150px; margin: 0 5px"
        ></el-input>
        <el-input
            v-model="location.latitude"
            placeholder="点击地图选择纬度"
            maxlength="15"
            readonly
            style="width: 150px"
        ></el-input>
    </div>
</div>
</template>

<script setup>
import AMapLoader from '@amap/amap-jsapi-loader';
window._AMapSecurityConfig = {
    securityJsCode: '你申请的安全密钥',
};
const props = defineProps({
    modelValue: {
        type: Object,
        default() {
            return {};
        },
    },
});
const emit = defineEmits(['update:modelValue']);
const map = shallowRef(null);
// 地点
const location = computed({
    get() {
       return props.modelValue;
    },
    set(val) {
       emit('update:modelValue', val);
    },
});
watch(location, (val) => {
    if (val.longitude && val.latitude) {
        drawMarker();
    }
  }
);
const keyword = ref('');
let placeSearch, AMapObj, marker, geocoder;
function initMap() {
    AMapLoader.load({
    key: '', // 申请好的Web端Key,首次调用 load 时必填
    version: '2.0'
    }).then(AMap => {
        AMapObj = AMap;
        map.value = new AMap.Map('mapcontainer');
        // 添加点击事件
        map.value.on('click', onMapClick);
        if (location.value.longitude) {
          drawMarker();
        }
        AMap.plugin(
            ['AMap.ToolBar','AMap.Scale','AMap.Geolocation','AMap.PlaceSearch', 'AMap.Geocoder'],
            () => {
            // 缩放条
            const toolbar = new AMap.ToolBar();
            // 比例尺
            const scale = new AMap.Scale();
            // 定位
            const geolocation = new AMap.Geolocation({
            enableHighAccuracy: true, //是否使用高精度定位,默认:true
            timeout: 10000, //超过10秒后停止定位,默认:5s
            position: 'RT', //定位按钮的停靠位置
            buttonOffset: new AMap.Pixel(10, 20), //定位按钮与设置的停靠位置的偏移量,默认:Pixel(10, 20)
            zoomToAccuracy: true, //定位成功后是否自动调整地图视野到定位点
        });
        geocoder = new AMap.Geocoder({
            city: '全国',
        });
        map.value.addControl(geolocation);
        map.value.addControl(toolbar);
        map.value.addControl(scale);
        placeSearch = new AMap.PlaceSearch({
            map: map.value,
            city: '',
            pageSize: 30, // 单页显示结果条数
            pageIndex: 1, // 页码
            citylimit: false, // 是否强制限制在设置的城市内搜索
            autoFitView: true,
        });
      }
    );
})
}
onMounted(() => {
    initMap();
});
// 搜索地图
function handleSearch(queryString, cb) {
    placeSearch.search(queryString, (status, result) => {
        if (result && typeof result === 'object' && result.poiList) {
            const list = result.poiList.pois;
            list.forEach(item => {
                item.value = item.name;
                item.label = item.name;
            });
            cb(list);
        } else {cb([])}
    });
}
// 点击地图
function onMapClick(e) {
    const { lng, lat } = e.lnglat;
    // 逆地理编码
    geocoder.getAddress([lng, lat], (status, result) => {
        if (status === 'complete' && result.info === 'OK') {
            const { addressComponent, formattedAddress } = result.regeocode;
            let { city, province, district } = addressComponent;
            if (!city) {
                // 直辖市
                city = province;
            }
            location.value = {
                longitude: lng,
                latitude: lat,
                address: formattedAddress,
                zone: [province, city, district],
            };
        }
    });
}
// 点击搜索项
function handleSelect(item) {
    const { pname, cityname, adname, address, name } = item;
    const { lng, lat } = item.location;
    location.value = {
        longitude: lng,
        latitude: lat,
        address,
        zone: [pname, cityname, adname],
        name,
    };
    map.value.setZoomAndCenter(16, [lng, lat]);
}
// 绘制地点marker
function drawMarker(val) {
    const { longitude, latitude } = location.value || val;
    if (marker) {
       marker.setMap(null);
    }
    marker = new AMapObj.Marker({
        position: new AMapObj.LngLat(longitude, latitude),
        anchor: 'bottom-center',
    });
    map.value.add(marker);
    map.value.setZoomAndCenter(16, [longitude, latitude]);
}
</script>

<style lang="scss" scoped>
.map-wrapper {
    position: relative;
    width: 100%;
    height: 400px;
    #mapcontainer {
        width: 100%;
        height: 100%;
    }
    .search-box {
        position: absolute;
        top: 10px;
        left: 10px;
        z-index: 1;
        display: flex;
        align-items: center;
    }
}
</style>

拓展

如果系统适配了暗黑模式,可以通过监听当前暗黑模式状态,来动态切换地图浅色主题和深色主题,从而实现地图暗黑模式的适配,这就留给大家自行探索了。

加载全部内容

相关教程
猜你喜欢
用户评论