初试百度地图:在vue3中使用百度地图

937 阅读1分钟

1. 使用前提

  • 到百度地图开发平台获取应用AK,设置Referer白名单

2. 在项目中引入地图

// index.html
<script type="text/javascript" src="https://api.map.baidu.com/api?v=3.0&ak=应用AK"></script>

3. 创建组件

<template>
    <div class="map"></div>
</template>

<script setup lang="ts">
import { defineExpose, defineEmits, ref, reactive } from 'vue'
// 地图实例
const map = ref()
// 经纬度
let point = reactive({})


/**
 * 初始化地图实例,添加地图点击事件
 * @param {object} pointObj 经纬度
 * @param {boolean} scrollWheelZoom 是否需要滚轮缩放
 * @return {void}
 */
const createdMap = (pointObj: any, scrollWheelZoom = true) => {
    map.value = new BMap.Map(document.querySelector('.map'));
    point = new BMap.Point(pointObj.lng, pointObj.lat);
    // 缩放倍数其实也可以通过参数传进来
    map.value.centerAndZoom(point, 15);
    // 鼠标滚轮是否可以缩放
    if (scrollWheelZoom) {
        map.value.enableScrollWheelZoom(true);
    }
    // 点击地图
    map.value.addEventListener('click', function (e: any) {
        emit('clickMap', e)
    });
}


/**
 * 添加标注(此处也应该把经纬度作为参数传递进来比较好)
 * @return {void}
 */
const createdMarker = () => {
    let marker = new BMap.Marker(point);
    map.value.addOverlay(marker);
}


/**
 *设置窗口信息
 * @param {object} opts 窗口标题,宽高等
 * @param {string} Dom  自定义DOM
 * @return {void}
 */
const setInfoWindow = (opts: any, Dom: any) => {
    var infoWindow = new BMap.InfoWindow(Dom, opts);
    map.value.openInfoWindow(infoWindow, map.value.getCenter());
}


/**
 *获取坐标的地址描述 
 * @param {object} point  经纬度
 * @return {Promise}
 */
const getLocation = (point: any) => {
    return new Promise((res, reg) => {
        let pointObj = new BMap.Point(point.lng, point.lat)
        var myGeo = new BMap.Geocoder();
        myGeo.getLocation(pointObj, function (result: any) {
            if (result) {
                res(result)
            } else {
                reg('...')
            }
        });
    })
}


/**
 *获取经纬度
 * @param {string} city  城市
 * @param {string} place 地点
 * @return {Promise}
 */
const getPoint = (city: any, place: any) => {

    return new Promise((res, reg) => {
        var myGeo = new BMap.Geocoder();
        myGeo.getPoint(place, function (point: any) {
            if (point) {
                res(point)
            } else {
                reg("找不到")
            }
        }, city)
    })
}


//
const emit = defineEmits(['clickMap'])
defineExpose({
    createdMap,
    createdMarker,
    getLocation,
    getPoint,
    setInfoWindow
})
</script>


<style scoped>
.map {
    width: 100%;
    height: 100%;
}
</style>
<style scoped lang="less">
/deep/.BMap_cpyCtrl,
/deep/ .anchorBL {
    display: none !important;
}
</style>

3. 在页面中使用

<template>
  <div class="map_box_my">

    <div class="dd">
      <a-cascader style="width:200px" v-model:value="city" :options="arr" placeholder="选择城市" />
      <a-input style="width:200px" v-model:value="place" placeholder="输入地点" />
      <a-button type="primary" @click="onSearch">搜索</a-button>
    </div>

    <bMapCom ref="childRef" @clickMap="clickMap"></bMapCom>

  </div>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { message } from 'ant-design-vue';
// 省市数据
import arr from './index.js'
// 地图组件
import bMapCom from '@/components/bMapCom/index.vue'
const childRef = ref(null)
const city = ref()
const place = ref()


// 初始化
onMounted(async () => {
  let point = {
    lng: '116.404',
    lat: '39.915'
  }
  // 通过经纬度获取地点的详细信息
  const data = await childRef.value.getLocation(point)
  let dom = `
                <h1>
                  ${data.surroundingPois[0] ? data.surroundingPois[0].title : place.value}
                </h1>
                <div>
                  ${data.address}${data.surroundingPois[0] ? '-' + data.surroundingPois[0].address : ''}
                </div>  
                `
  // 创建地图
  childRef.value.createdMap(point)
  // 添加标注
  childRef.value.createdMarker()
  // 设置窗口信息
  childRef.value.setInfoWindow({}, dom)
})


// 点击地图
const clickMap = async (e: any) => {
  // 通过经纬度获取地点的详细信息
  const data = await childRef.value.getLocation(e.point)
  message.success(`经度:${e.point.lng}--纬度:${e.point.lat}--地点:${data.address}`);
}


// 输入地点搜索
const onSearch = async () => {
  if (city.value && city.value.length && place.value) {
    try {
      // 根据搜索地点获取经纬度
      const res = await childRef.value.getPoint(city.value[city.value.length - 1], place.value)
      // 通过经纬度获取地点的详细信息
      const data = await childRef.value.getLocation(res)
      let dom = `
                <h1>
                  ${data.surroundingPois[0] ? data.surroundingPois[0].title : place.value}
                </h1>
                <div>
                  ${data.address}${data.surroundingPois[0] ? '-' + data.surroundingPois[0].address : ''}
                </div>  
                `;
      // 创建地图
      childRef.value.createdMap(res)
      // 添加标注
      childRef.value.createdMarker()
      // 设置窗口信息
      childRef.value.setInfoWindow({}, dom)

    } catch (err) {
      console.log(err)
    }
  } else {
    message.error('城市和地点都不能为空,否则搜索不到');
  }
}

</script>


<style lang="less" scoped>
.map_box_my {
  width: 100vw;
  height: 100vh;
  position: relative;
}
.dd {
  position: absolute;
  z-index: 999;
  left: 20px;
  top: 20px;
  display: flex;
  padding: 10px;
  background: #fff;
  border-radius: 5px;
  box-shadow: 0 0 30px 1px #999
}
</style>

4. 图

QQ图片20220903015804.png

QQ图片20220903015810.png

QQ图片20220903015907.png

5. 后续