Vue中引入百度地图(实现缩放,标记,信息窗)

时间:2024-04-17 10:16:50

背景:在使用Vue做项目的时候,需要使用百度地图,使用了 vue-baidu-map插件

实现的功能包括:地图的缩放,动态比例尺,动态设置地图中心点,根据经纬度在地图上进行标点,点击标记点打开信息窗口展示详情

开工之前需要在项目中安装 ` vue-baidu-map` 的依赖

npm install vue-baidu-map --save

1.引入方式

  • 可以在 app.js 中全局引入(如果不是每个组件中都使用此组件不推荐全局引入)
import BaiduMap from \'vue-baidu-map\'

Vue.use(BaiduMap, {
    /*  需要你在百度开放平台上注册,并申请ak */
  /*  项目上线时,记得要使用公司信息注册的ak  */
ak:\'YOUR_APP_KEY\'
})
  • 局部引入,引入方式与全局引入不同,需要在node_modules/vue-baidu-map/components 里面找到需要的组件

    注意:局部引入要在 `<baidu-map ak=\'\'></baidu-map>`中声明ak属性

//项目中引入使用百度地图的组件
import BaiduMap from \'vue-baidu-map/components/map/Map.vue\'    // 百度地图组件
import BmScale from \'vue-baidu-map/components/controls/Scale\'   // 比例尺组件
import BmNavigation from \'vue-baidu-map/components/controls/Navigation\'  // 缩放组件 
import BmMarker from \'vue-baidu-map/components/overlays/Marker\'  // 标记点的组件
import BmLabel from \'vue-baidu-map/components/overlays/Label\'    // 标签组件,展示在标记点中的数字
import BmInfoWindow from \'vue-baidu-map/components/overlays/InfoWindow\'  // 信息窗体

// 组件的注册
export default {
    components: {
        BaiduMap,
        BmScale,
        BmNavigation,
        BmMarker,
        BmInfoWindow,
        BmLabel
      },  
}

2.在组件中的使用,代码如下

<baidu-map
            class="bm-view"
            :center="center"   // 动态设置中心点,center数据格式 => center:{lng:116.404,lat:39.915},可根据定位到不同的城市,动态改变值
            :zoom="zoom"    //  地图显示比例尺的大小,必须定义,有1~19个级别
            @ready="handler"   //  地图API加载完毕后执行的代码
            :scroll-wheel-zoom="true"   //  鼠标滚轮控制缩放
            :mapClick="false"       //  禁止点击景点弹出信息窗体,自定义的除外
            ak="YOUR_APP_KEY"       //  你申请的ak值
          >
            <!-- 比例尺控件,注册此组件才会在地图上显示比例尺 -->
            <bm-scale anchor="BMAP_ANCHOR_TOP_RIGHT"></bm-scale>
            <!-- 缩放控件,注册此组件才会显示拖放进度 -->
            <bm-navigation anchor="BMAP_ANCHOR_TOP_RIGHT"></bm-navigation>
            <div v-for="(marker, index) in markers" :key="marker.id">
         <!-- 标记点组件 -->
              <bm-marker
                :position="{ lng: marker.lng, lat: marker.lat }"
                :title="marker.servestationname"
                @click="infoWindowOpen(marker)"
              >
          <!-- 信息窗体组件 -->
                <bm-info-window
                  :title="marker.servestationname"
                  :position="{ lng: marker.lng, lat: marker.lat }"
                  :show="marker.showFlag"
                  @close="infoWindowClose(marker)"
                >
                  <p>
                    {{ marker.servestationaddress }}
                  </p>
                  <p>服务车型:{{ marker.brandandcartype }}</p>
                  <p>联系人:{{ marker.handler }}</p>
                  <p>联系热线:{{ marker.phone }}</p>
                </bm-info-window>
          <!-- 标签组件 -->
                <bm-label
                  :content="index + 1 + \'\'"
                  :labelStyle="{
                    color: \'#fff\',
                    fontSize: \'12px\',
                    background: \'rgba(0, 0, 0, 0)\',
                    borderColor: \'rgba(0, 0, 0, 0)\',
                  }"
                  :offset="{ width: index >= 9 ? 0 : 4, height: 2 }"
                />
              </bm-marker>
            </div>
          </baidu-map>

export default {
     data() {
    return {
      center: { lng: null, lat: null },
      zoom: 13,
      // 地图标记点数据
      markers: [
          {
           lng: 116.405,
           lat: 39.901,
           showFlag: false, //flag放在每一条数据里
         },
         {
           lng: 116.404,
           lat: 39.9,
           showFlag: false,
         },
      ]
    }
  },
    methods: {
        // 地图初始化完成回调
        handler({ BMap, map }) {
          this.center.lng = 116.404
          this.center.lat = 39.915
        },
        // 关闭标记详情
        infoWindowClose(marker) {
          marker.showFlag = false
        },
        // 打开标记详情
        infoWindowOpen(marker) {
          marker.showFlag = !marker.showFlag
        },
    }
}
View Code

3.总结使用过程中遇见的问题

  这几个问题是来自组件文档的温馨提示,已亲测

  • BaiduMap 组件容器本身是一个空的块级元素,如果容器不定义高度,百度地图将渲染在一个高度为 0 不可见的容器内。
  • 没有设置 centerzoom 属性的地图组件是不进行地图渲染的。当center 属性为合法地名字符串时例外,因为百度地图会根据地名自动调整 zoom 的值。

    

  • 由于百度地图 JS API 只有 JSONP 一种加载方式,因此 BaiduMap 组件及其所有子组件的渲染只能是异步的。因此,请使用在组件的 ready 事件来执行地图 API 加载完毕后才能执行的代码,不要试图在 vue 自身的生命周期中调用 BMap 类,更不要在这些时机修改 model 层。

  现在总结下本次遇见的问题

  • 第一次在项目中使用,所以组件内引入组件有点晕,在经过一番百度之后,发现需要去依赖中找路径,和你需要的各个组件;每个功能都是一个组件!!!
  • 缩放组件问题,注册完成后,鼠标滚轮不能进行缩放,问题是要在 `<baidu-map>` 标签上配置 `:scroll-wheel-zoom="true"`
  • 比例尺,缩放组件的 anchor属性是配置元素在地图上显示的位置,参数详见文档
  • 关于给你经纬度信息,如何在地图上标记出来的问题,这里需要使用 marker 组件,因为不是一个标记点,需要渲染很多标记点,所以会出现很多问题

  ① 在bm-marker中使用v-for循环,但是bm-info-window只会创建一个

  方案:在 marker 组件的外面套一层 div,使用 v-for 在上面进行渲染

  ② 创建的出来的标记点个数不固定,怎么按序号展示呢?

  方案:这里需要使用 baidu-map 提供的 Label 组件,在这里需要给组件提供内容,样式,展示的偏移位置,用到的属性为:content,labelStyle,offset

  ③ 创建的出来的标记点,点击怎么会显示当前城市的详情呢?

  方案:这里需用 bm-info-window 组件,组件的标签内写需要的内容,该组件的 title 属性为信息窗的标题,可动态写入;组件的 show 属性控制显示/隐藏,position属性控制窗体位置

  ④在切换多个城市坐标时,标记点 根据上面 代码中的 markers 数据动态渲染,再点击标记点时,信息窗不能弹出

  问题排查:经过调试,发现点击事件可以触发,可以拿到最新的 markers 数据,但是事件传参的对象确是第一次的数据,疑惑?这应该是dom没有更新,看到外层的 v-for 渲染时,为了偷懒,key属性的值用的是index,切换坐标时,重新渲染的标记点的key值相同,所以 虚拟dom 的惰性触发,这里改成 id就解决啦!

  ⑤ 在自定义信息窗样式时,要写在全局样式中

  • 下面奉上比例尺级别对应的数据

         

 

经过一路的踩坑,终于完成啦!

    

   传送门:vue-baidu-map中文文档