[前端] Vue3管理后台项目使用高德地图选点的实现

2717 0
Honkers 2022-10-21 15:43:46 | 显示全部楼层 |阅读模式
目录

    前言获取地图Key引入地图 JSAPI初始化地图地图选点组件化使用拓展


前言

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

获取地图Key

    登录高德开放平台创建应用,添加Key,选择Web端(JS API),生成Key和安全密钥

引入地图 JSAPI

项目中使用了官方推荐的 JSAPI Loader 来加载地图
    安装官方 npm 包 @amap/amap-jsapi-loader配置安全密钥(不安全的方式),其它配置方式在这里
  1. <script setup>
  2. import AMapLoader from '@amap/amap-jsapi-loader';
  3. window._AMapSecurityConfig = {
  4.   securityJsCode: '你申请的安全密钥',
  5. };
  6. </script>
复制代码
初始化地图

    创建一个id为mapContainer的div元素调用initMap方法初始化相关地图插件
  1. <script setup>
  2. const map = shallowRef(null);
  3. let AMapObj;
  4. function initMap() {
  5.    AMapLoader.load({
  6.      key: '你申请的Key',
  7.      version: '2.0',
  8.    }).then(AMap => {
  9.         AMapObj = AMap;
  10.         map.value = new AMap.Map('mapContainer');
  11.       })
  12. }
  13. </script>
复制代码
地图选点

项目中提供搜索选点和直接点击地图选点两种方法
    搜索选点:使用 element-plus 的 autocomplete 组件结合地图搜索服务实现下拉选择地点点击选点:借助地图点击事件获取地点的经纬度信息,然后使用地图逆地理编码api解析出地址信息 选择地点之后同步绘制 marker 标记,同时将 marker 移动到地图中心点并设置缩放比例

组件化使用

为了方便一整套逻辑的复用,我将以上流程全部封装到一个组件中,通过 v-model 绑定所选地点的详细信息,方便选择地点之后将信息同步到父组件。
下面贴出组件全部的代码
  1. <template>
  2. <div class="map-wrapper">
  3.     <div id="mapcontainer"></div>
  4.     <div class="search-box">
  5.         <el-autocomplete
  6.             v-model="keyword"
  7.             :fetch-suggestions="handleSearch"
  8.             :trigger-on-focus="false"
  9.             clearable
  10.             placeholder="输入城市+关键字搜索"
  11.             @select="handleSelect"
  12.             style="width: 300px"
  13.         />
  14.         <el-input
  15.             v-model="location.longitude"
  16.             placeholder="点击地图选择经度"
  17.             maxlength="15"
  18.             readonly
  19.             style="width: 150px; margin: 0 5px"
  20.         ></el-input>
  21.         <el-input
  22.             v-model="location.latitude"
  23.             placeholder="点击地图选择纬度"
  24.             maxlength="15"
  25.             readonly
  26.             style="width: 150px"
  27.         ></el-input>
  28.     </div>
  29. </div>
  30. </template>
  31. <script setup>
  32. import AMapLoader from '@amap/amap-jsapi-loader';
  33. window._AMapSecurityConfig = {
  34.     securityJsCode: '你申请的安全密钥',
  35. };
  36. const props = defineProps({
  37.     modelValue: {
  38.         type: Object,
  39.         default() {
  40.             return {};
  41.         },
  42.     },
  43. });
  44. const emit = defineEmits(['update:modelValue']);
  45. const map = shallowRef(null);
  46. // 地点
  47. const location = computed({
  48.     get() {
  49.        return props.modelValue;
  50.     },
  51.     set(val) {
  52.        emit('update:modelValue', val);
  53.     },
  54. });
  55. watch(location, (val) => {
  56.     if (val.longitude && val.latitude) {
  57.         drawMarker();
  58.     }
  59.   }
  60. );
  61. const keyword = ref('');
  62. let placeSearch, AMapObj, marker, geocoder;
  63. function initMap() {
  64.     AMapLoader.load({
  65.     key: '', // 申请好的Web端Key,首次调用 load 时必填
  66.     version: '2.0'
  67.     }).then(AMap => {
  68.         AMapObj = AMap;
  69.         map.value = new AMap.Map('mapcontainer');
  70.         // 添加点击事件
  71.         map.value.on('click', onMapClick);
  72.         if (location.value.longitude) {
  73.           drawMarker();
  74.         }
  75.         AMap.plugin(
  76.             ['AMap.ToolBar','AMap.Scale','AMap.Geolocation','AMap.PlaceSearch', 'AMap.Geocoder'],
  77.             () => {
  78.             // 缩放条
  79.             const toolbar = new AMap.ToolBar();
  80.             // 比例尺
  81.             const scale = new AMap.Scale();
  82.             // 定位
  83.             const geolocation = new AMap.Geolocation({
  84.             enableHighAccuracy: true, //是否使用高精度定位,默认:true
  85.             timeout: 10000, //超过10秒后停止定位,默认:5s
  86.             position: 'RT', //定位按钮的停靠位置
  87.             buttonOffset: new AMap.Pixel(10, 20), //定位按钮与设置的停靠位置的偏移量,默认:Pixel(10, 20)
  88.             zoomToAccuracy: true, //定位成功后是否自动调整地图视野到定位点
  89.         });
  90.         geocoder = new AMap.Geocoder({
  91.             city: '全国',
  92.         });
  93.         map.value.addControl(geolocation);
  94.         map.value.addControl(toolbar);
  95.         map.value.addControl(scale);
  96.         placeSearch = new AMap.PlaceSearch({
  97.             map: map.value,
  98.             city: '',
  99.             pageSize: 30, // 单页显示结果条数
  100.             pageIndex: 1, // 页码
  101.             citylimit: false, // 是否强制限制在设置的城市内搜索
  102.             autoFitView: true,
  103.         });
  104.       }
  105.     );
  106. })
  107. }
  108. onMounted(() => {
  109.     initMap();
  110. });
  111. // 搜索地图
  112. function handleSearch(queryString, cb) {
  113.     placeSearch.search(queryString, (status, result) => {
  114.         if (result && typeof result === 'object' && result.poiList) {
  115.             const list = result.poiList.pois;
  116.             list.forEach(item => {
  117.                 item.value = item.name;
  118.                 item.label = item.name;
  119.             });
  120.             cb(list);
  121.         } else {cb([])}
  122.     });
  123. }
  124. // 点击地图
  125. function onMapClick(e) {
  126.     const { lng, lat } = e.lnglat;
  127.     // 逆地理编码
  128.     geocoder.getAddress([lng, lat], (status, result) => {
  129.         if (status === 'complete' && result.info === 'OK') {
  130.             const { addressComponent, formattedAddress } = result.regeocode;
  131.             let { city, province, district } = addressComponent;
  132.             if (!city) {
  133.                 // 直辖市
  134.                 city = province;
  135.             }
  136.             location.value = {
  137.                 longitude: lng,
  138.                 latitude: lat,
  139.                 address: formattedAddress,
  140.                 zone: [province, city, district],
  141.             };
  142.         }
  143.     });
  144. }
  145. // 点击搜索项
  146. function handleSelect(item) {
  147.     const { pname, cityname, adname, address, name } = item;
  148.     const { lng, lat } = item.location;
  149.     location.value = {
  150.         longitude: lng,
  151.         latitude: lat,
  152.         address,
  153.         zone: [pname, cityname, adname],
  154.         name,
  155.     };
  156.     map.value.setZoomAndCenter(16, [lng, lat]);
  157. }
  158. // 绘制地点marker
  159. function drawMarker(val) {
  160.     const { longitude, latitude } = location.value || val;
  161.     if (marker) {
  162.        marker.setMap(null);
  163.     }
  164.     marker = new AMapObj.Marker({
  165.         position: new AMapObj.LngLat(longitude, latitude),
  166.         anchor: 'bottom-center',
  167.     });
  168.     map.value.add(marker);
  169.     map.value.setZoomAndCenter(16, [longitude, latitude]);
  170. }
  171. </script>
  172. <style lang="scss" scoped>
  173. .map-wrapper {
  174.     position: relative;
  175.     width: 100%;
  176.     height: 400px;
  177.     #mapcontainer {
  178.         width: 100%;
  179.         height: 100%;
  180.     }
  181.     .search-box {
  182.         position: absolute;
  183.         top: 10px;
  184.         left: 10px;
  185.         z-index: 1;
  186.         display: flex;
  187.         align-items: center;
  188.     }
  189. }
  190. </style>
复制代码
拓展

如果系统适配了暗黑模式,可以通过监听当前暗黑模式状态,来动态切换地图浅色主题和深色主题,从而实现地图暗黑模式的适配,这就留给大家自行探索了。
到此这篇关于Vue3管理后台项目使用高德地图选点的实现的文章就介绍到这了,更多相关Vue3 高德地图选点内容请搜索中国红客联盟以前的文章或继续浏览下面的相关文章希望大家以后多多支持中国红客联盟!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Honkers

荣誉红客

关注
  • 4009
    主题
  • 36
    粉丝
  • 0
    关注
这家伙很懒,什么都没留下!

中国红客联盟公众号

联系站长QQ:5520533

admin@chnhonker.com
Copyright © 2001-2025 Discuz Team. Powered by Discuz! X3.5 ( 粤ICP备13060014号 )|天天打卡 本站已运行