wangbd-myui
Version:
MY前端基础框架核心组件库
191 lines (182 loc) • 4.84 kB
JavaScript
/**
* 聚合组件
* @module $ui/map/my-map-cluster
*/
import Point from 'ol/geom/Point';
import Feature from 'ol/Feature';
import VectorLayer from 'ol/layer/Vector'
import {Cluster, Vector as VectorSource} from 'ol/source';
import parseStyle from '../../utils/style'
// 样式函数构造器
const defaultStyleCreator = config => {
return feature => {
const size = (feature.get('features') || []).length
const {fill, radius, strokeWidth, strokeColor, textFill, scaleSeed} = config
return parseStyle({
circle: {
radius: radius + scaleSeed * size,
stroke: {
width: strokeWidth,
color: strokeColor
},
fill: fill
},
text: {
text: size > 0 ? size.toString() : '',
fill: textFill
}
})
}
}
export default {
name: 'MyMapCluster',
inject: ['myMap'],
render(h) {
const children = this.$slots.default
if (children && children.length > 1) {
return h('div', children)
}
return children
},
/**
* 属性参数
* @member props
* @property {Object[]} [data] 数据
* @property {Object} [keyMap] 数据字段映射
* @property {string} [keyMap.coordinate=coordinate] 经纬度字段名称
* @property {number} [distance=20] 聚合像素距离
* @property {Object|Function} [styleCreator] 样式配置对象或函数
* @property {string} [styleCreator.fill] 背景颜色
* @property {number} [styleCreator.radius] 半径
* @property {number} [styleCreator.strokeWidth] 描边宽度
* @property {string} [styleCreator.strokeColor] 描边颜色
* @property {string} [styleCreator.textFill] 字体颜色
* @property {number} [styleCreator.scaleSeed] 半径缩放因子
* @property {boolean} [cluster=true] 开启聚合
* @property {number} [zIndex] 图层层级
*/
props: {
// 数据 [{coordinate}]
data: {
type: Array,
default() {
return []
}
},
// 数据字段映射
keyMap: {
type: Object,
default() {
return {
coordinate: 'coordinate'
}
}
},
// 聚合像素距离
distance: {
type: Number,
default: 20
},
// 样式配置对象或函数
styleCreator: {
type: [Object, Function],
default() {
return {
fill: '#409eff',
radius: 10,
strokeWidth: 1,
strokeColor: '#fff',
textFill: '#fff',
scaleSeed: 0.001
}
}
},
// 开启聚合
cluster: {
type: Boolean,
default: true
},
zIndex: Number,
cursor: Boolean
},
watch: {
data(val) {
this.clear()
this.draw(val)
}
},
methods: {
init(map) {
if (this.layer) return
const source = new VectorSource({})
const clusterSource = new Cluster({
distance: this.distance,
source
});
clusterSource.on('change', this.handleClusterChange)
const style = typeof this.styleCreator === 'function'
? this.styleCreator
: defaultStyleCreator(this.styleCreator)
this.layer = new VectorLayer({
source: this.cluster ? clusterSource : source,
zIndex: this.zIndex,
style
})
map.addLayer(this.layer)
this.draw(this.data)
this.$emit('ready', this)
},
dispose() {
if (this.myMap && this.myMap.map && this.layer) {
const source = this.layer.getSource()
source && source.un('change', this.handleClusterChange)
this.myMap.map.removeLayer(this.layer)
}
},
/**
* 绘制图形
* @method draw
* @param {Object[]} data 数据据
*/
draw(data = []) {
const {coordinate} = this.keyMap
const features = data.map(item => new Feature({
geometry: new Point(item[coordinate]),
data: item,
__vm__: this
}))
if (this.layer) {
const source = this.getSource()
source && source.addFeatures(features)
}
},
/**
* 清除图形
* @method clear
*/
clear() {
if (!this.layer) return
const source = this.getSource()
source && source.clear()
},
getSource() {
if (!this.layer) return
const source = this.layer.getSource()
return this.cluster ? source.getSource() : source
},
handleClusterChange(e) {
/**
* Cluster 发生改变时触发
* @event change
* @param {Object} e
*/
this.$emit('change', e)
}
},
created() {
this.myMap.mapReady(this.init)
},
beforeDestroy() {
this.dispose()
}
}