Vue中引入百度地图(实现缩放,标记,信息窗)
背景:在使用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 }, } }
3.总结使用过程中遇见的问题
这几个问题是来自组件文档的温馨提示,已亲测
BaiduMap
组件容器本身是一个空的块级元素,如果容器不定义高度,百度地图将渲染在一个高度为 0 不可见的容器内。- 没有设置
center
和zoom
属性的地图组件是不进行地图渲染的。当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就解决啦!
⑤ 在自定义信息窗样式时,要写在全局样式中
- 下面奉上比例尺级别对应的数据
经过一路的踩坑,终于完成啦!