Vue中如何在ElementUI的dialog组件中引入BaiduMap?

1,010 阅读1分钟

这是我参与2022首次更文挑战的第1天

获取某个地点的经纬度信息,在后台管理系统中是比较常见的,这次在开发中也有相应的需求,下面我把实现的思路和大家一起分享,写的不好的地方请大家多多指正!

1、下载 vue-baidu-map 模块

npm install vue-baidu-map --save

2、在 main.js 文件中全局引入

import BaiduMap from 'vue-baidu-map'
Vue.use(BaiduMap, {
  ak: AK // 这里的AK是百度的密钥
})

3.在页面的组件中引入 BaiduMap

<el-dialog
  title="经纬度选择"
  :visible.sync="mapDialogVisible"
  :close-on-click-modal="false"
  width="50%"
>
  <el-form label-position="right" label-width="120px">
    <el-form-item label="详细地址">
      <el-autocomplete
        v-model="address"
        :fetch-suggestions="kwSearch"
        placeholder="请输入详细地址"
        style="width: 100%"
        :trigger-on-focus="false"
        :debounce=0
        @select="handleSelectAddress"
      />
    </el-form-item>
  </el-form>

  <baidu-map class="map" :center="center" :zoom="zoom" @ready="handler" :scroll-wheel-zoom="true" @click="clickMap">
    <bm-geolocation anchor="BMAP_ANCHOR_BOTTOM_RIGHT" :showAddressBar="true" :autoLocation="true"></bm-geolocation>
    <bm-city-list anchor="BMAP_ANCHOR_TOP_LEFT"></bm-city-list>
  </baidu-map>
  <div slot="footer" class="dialog-footer">
    <el-button @click="handleMapSubmit" type="primary">提交</el-button>
    <el-button @click="mapDialogVisible = false">返回</el-button>
  </div>
</el-dialog>

<script>
  import loadBMap from '@/utils/loadBMap.js'
  const AK = '你的百度密钥'
  let local = null

  export default {
    data() {
      return {
        // 经纬度选择对话框
        mapDialogVisible: false,
        address: '',
        longitude: null,
        latitude: null,
        center: {
          lng: 113.27,
          lat: 23.13
        },
        zoom: 15,
        map: null,
        BMap: null
      }
    },
    async mounted() {
      await loadBMap(AK)
    },
    methods: {
      handler ({BMap, map}) {
        this.map = map
        this.BMap = BMap
        let _this = this
        // 调用百度地图api 中的获取当前位置接口
        geolocation.getCurrentPosition(function (r) {
          let myGeo = new BMap.Geocoder()
          myGeo.getLocation(new BMap.Point(r.point.lng, r.point.lat), function (result) {
            if (result) {
              _this.showMap({lng: result.point.lng, lat: result.point.lat})
              _this.longitude = result.point.lng
              _this.latitude = result.point.lat
            }
          })
        })
        //开启鼠标滚轮缩放
        this.map.enableScrollWheelZoom(true)
      },
      clickMap(e) {
        this.removeAllMarker(this.map)
        const point = e.point
        const marker = new BMap.Marker(point)
        this.map.addOverlay(marker)
        this.longitude = point.lng
        this.latitude = point.lat
      },
      // 清除地图上的所有覆盖物
      removeAllMarker(map) {
        if (map) {
          let overlays = map.getOverlays()
          overlays.forEach((marker, index, arr) => {
            map.removeOverlay(marker)
          })
        }
      },
      // 提交按钮点击事件
      handleMapSubmit() {
        // 给经纬度赋值
        this.rowFormTempData.lat = this.latitude;
        this.rowFormTempData.lng = this.longitude;
        // 关闭经纬度选择对话框
        this.mapDialogVisible = false
      },
      // 根据输入的关键词进行搜索
      kwSearch(keyword, callback) {
        let options = {
          onSearchComplete: function(results) {
            if (local1.getStatus() === 0) {
              // 判断状态是否正确
              var temp = []
              for (let i = 0; i < results.getCurrentNumPois(); i++) {
                const x = results.getPoi(i)
                const item = { value: x.address + x.title, point: x.point }
                temp.push(item)
                callback(temp)
              }
            } else {
              callback([])
            }
          }
        }
        var local1 = new this.BMap.LocalSearch(this.map, options)
        local1.search(keyword)
      },
      // 选中搜索建议项
      handleSelectAddress(item) {
        let { point } = item
        this.latitude = point.lat
        this.longitude = point.lng
        this.showMap({lng: point.lng, lat: point.lat})
      },
      // 在地图上画点
      showMap (point) {
        setTimeout(() => {
          //移除地图覆盖物
          this.map.centerAndZoom(point, 15)
          this.map.clearOverlays()
          if (point && point.lng && point.lat) {
            let marker = new BMap.Marker(point)
            this.map.addOverlay(marker)
            this.center = point
          }
        }, 500)
      },
      
      // 点击编辑时根据已有的经纬度信息在地图上画点
      // 地图经纬度选择
      handleMapSelect() {
        this.mapDialogVisible = true;
        this.address = '';
        this.showMap({lng: this.rowFormTempData.lng, lat: this.rowFormTempData.lat})
      },
    },
  }
</script>

在使用BaiduMap过程中,有可能会出现BMap is not defined 报错信息,所以页面引入了 loadBMap.js 文件就是用来解决 BMap is not defined 这个问题的。 具体代码如下:

  /**
   * 动态加载百度地图api函数
   * @param {String} ak  百度地图AK,必传
   */
   export default function loadBMap(ak) {
    return new Promise(function(resolve, reject) {
      if (typeof window.BMap !== 'undefined') {
        resolve(window.BMap)
        return true
      }
      window.onBMapCallback = function() {
        resolve(window.BMap)
      }
      let script = document.createElement('script')
      script.type = 'text/javascript'
      script.src = 'http://api.map.baidu.com/api?v=3.0&ak=' + ak + '&callback=onBMapCallback'
      script.onerror = reject
      document.head.appendChild(script)
    })
  }

如果要去除地图左下角的版权和文字信息,可以在 style 里面加入以下的样式

<style scoped>
  /deep/.BMap_cpyCtrl {
    display: none !important;
  }
  /deep/.anchorBL {
    display: none !important;
  }
</style>

未加样式之前:

image.png

加了样式之后:

image.png

关于 vue-baidu-map 这个插件的使用,大家可以查阅官方文档! vue-baidu-map  官网地址