介绍

最初的灵感来源于,能否实现动态创建一个 vue 组件,并添加到页面上显示出来。

后来开发地图场景,需要使用 mapbox 的 marker 做地图扎点,而 mapbox 的扎点实际使用的是 dom ,如此一来便萌生了能否使用 vue 来做扎点的想法。

在经历几个版本的迭代后,迎来了 mapbox-vue-marker 的诞生!

使用Mapbox-Vue-Marker,你可以通过 vue 组件的方式,向地图添加扎点marker,实现完全由数据驱动的UI逻辑,工欲善其事必先利其器,方能事半功倍!

安装

npm install mapbox-vue-marker --save

目前仅支持通过 npm 安装

注意!本插件需要同时使用vue和mapboxgl

国内建议使用 cnpm 进行安装

cnpm install mapbox-vue-marker --save

注册组件

通过 npm 安装之后,需要在 main.js 注册该插件

import store from './store'
import mapboxgl from 'mapbox-gl'
import 'mapbox-gl/dist/mapbox-gl.css'
import mapboxvuemarker from 'mapbox-vue-marker'

let plugOptions = {
  mapboxgl,router,store,
  // 可通过rename修改默认的方法名
  // rename:{
  //   '$addMarker':'addMK',
  //   '$removeMarker':'delMk',
  //   '$makeMarker':'makeMK'
  // }
}

Vue.use(mapboxvuemarker,plugOptions)

Vue.config.productionTip = false

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

提示

router和store是可选参数

通过 Vue 提供的use方法注册该组件,传入插件对象和配置对象

配置对象的参数如下

options = {
    mapboxgl,	//mapboxgl对象(必须)
    router,		//vue的router(可选)
    store,		//vuex对象(可选)
}

到此插件的配置就完成了!

重命名插件方法

我们向 Vue 的原型链上添加了三个基础方法,为了排除命名冲突的问题,我们提供了修改命名的方法

插件在 main.js 中注册的时候,可传递一个 rename 字段,该字段的值必须是一个对象。

let plugOptions = {
  mapboxgl,router,store,
  rename:{
    '$addMarker':'addMK',
    '$removeMarker':'delMk',
    '$makeMarker':'makeMK'
  }
}

Vue.use(mapboxvuemarker,plugOptions)

上述代码可以看出,键名为要修改的方法,键值为修改的结果

$makeMarker 创建marker

在配置好环境以后,我们正式开始创建marker,以下是一个创建marker的小例子 首先我们创建一个基本的 vue 组件

<template>
    <div class="vuemarker">V</div>
</template>

<script>
    export default {
        name: "vuemarker",
    }
</script>

现在我们把这个 vue 组件导出

mapboxgl.accessToken = 'token';
var map = new mapboxgl.Map({
	container: 'map',
    style: 'mapbox://styles/mapbox/streets-v11', 
    center: [-74.50, 40],
    zoom: 9 
});
let marker = this.$makeMarker({
    lnglat:map.getCenter(),
    component:vuemarker,
});

上述代码创建了一个最基本的mapbox地图,然后通过插件的全局方法 $makeMarker 方法创建了一个marker对象,并赋值给 marker 变量

提示

$makeMarker方法接受一个配置对象,返回标准的mapbox的marker对象

$makeMarker的详细配置参数有:

let options = {
	lnglat,//marker在地图上的经纬度(必须)
	component,//组成marker的 vue 组件
	anchor,//marker的中心点,详情见mapbox官网介绍,默认为bottom
	props,//vue组件接收的参数对象,默认为空对象
	draggable,//marker是否可拖动,默认为false
	zIndex,//扎点的层级,默认为空
}

注意

$makeMarker的作用仅仅是创建marker

$addMarker 添加marker到地图

此时还需要调用$addMarker方法来添加marker到地图

this.$addMarker(this.marker,map)

$addMarker的两个参数都为必填项,第一个参数可以是marker对象,也可以是包含marker的数组或对象,第二个参数为map对象

方法内部会遍历参数对象的所有深度,移除参数对象包含的所有marker

注意

只有那些通过$makeMarker方法制造的marker才能被该方法添加到地图

$removeMarker 移除marker

$removeMarker方法可以移除在地图上的marker

this.$removeMarker(this.marker)

该方法需要一个参数,即要移除的marker,和添加的方法相同,这个参数也可以是一个包含marker的数组或对象

注意

只有那些通过$makeMarker方法制造的marker才能被该方法从地图移除

$getMarkerBox 数据存储

一定要注意

🙃如果没有开启markerBox,千万不要将marker放入vue组件的data中

🙃这会导致vue向marker对象设置无效的getter和setter

🙃您可能会需要手动实现marker的存储,并在beforeDestroy钩子中销毁

在实际项目中,更多可能的是会面临多种类多数量的marker

在此提供一种保存数据的想法

let markerbox = this.getMarkerBox()

如果需要插件来代理存储marker,您需要在调用$makeMarker方法时传入参数usebox(boolean)和markerType(string)

let markerbox={
    type1:[marker],
    other:[]
}

传入的类型会被存储为markerbox对象下的数组

提示

开启usebox功能后,如果没有传入markerType,那么这个marker将被归类到other分类下

行为分析

标准对象

$addMarker 和 $removeMarker 仅对与通过 $makeMarker 方法构建的marker生效

vue-marker组件默认行为

$makeMarker 构造完毕后,会立刻执行 vue 组件的 mounted 方法,并且将一直处于挂载状态

考虑到业务中的逻辑,我们提供了 $addMarker 和 $removeMarker 的回调方法,您可以在 vue 组件的 methods 中提供 onAdd 和 onRemove 方法,它们将作为回调方法自动调用

marker层级

我们默认接管了 marker 的层级关系,它在每次拖动地图时,都会进行计算并更新层级参数

您可以在构建 marker 时传入 zIndex 来设置为固定层级

参数传递

我们默认向 vue 组件提供了两个 props ,分别是 marker 对象和 parent 对象,parent 指向调用构造 marker 方法的 vue 实例

marker对象默认行为

mapbox 的 marker 也具有默认行为,当您调用 $addMarker 的时候,它将首先调用一次 remove方法,您需要注意调用回调时,可能产生不可预知的错误