wangbd-myui
Version:
MY前端基础框架核心组件库
311 lines (303 loc) • 8.13 kB
JavaScript
/**
* Draw 绘画组件
* @module $ui/map/my-map-draw
*/
import VectorLayer from 'ol/layer/Vector'
import {Vector as VectorSource} from 'ol/source'
import {Draw, Snap, Modify} from 'ol/interaction'
import GeoJSON from 'ol/format/GeoJSON'
import parseStyle from '../../utils/style'
// 默认图形样式
const defaultEffect = {
fill: 'rgba(255, 255, 255, 0.5)',
stroke: {
color: '#409eff',
width: 2
},
circle: {
radius: 6,
fill: '#409eff',
stroke: {
width: 1,
color: '#fff'
}
}
}
export default {
name: 'MyMapDraw',
inject: ['myMap'],
render() {
return this.$slots.default
},
/**
* 属性参数
* @member props
* @property {string} [type=LineString] 图形类型,支持 'Point', 'LineString', 'Polygon', 'Circle'
* @property {object|function} [brush] 画笔样式配置
* @property {object|function} [effect] 图形样式配置
* @property {boolean} [manual] 启用手动控制,启用后,可按需要调用 draw modify finish 方法完成画图功能
* @property {object} [options] Draw组件附加参数对象,支持:{clickTolerance,dragVertexDelay,snapTolerance,stopClick,maxPoints,minPoints,freehand,wrapX}
*/
props: {
type: {
type: String,
default: 'LineString',
validator(val) {
return ['Point', 'LineString', 'Polygon', 'Circle'].includes(val)
}
},
// 画笔样式
brush: {
type: [Object, Function]
},
// 图形样式
effect: {
type: [Object, Function],
default() {
return defaultEffect
}
},
// 手动控制
manual: Boolean,
/*
{
clickTolerance: Number,
dragVertexDelay: Number,
snapTolerance: Number,
stopClick: Boolean,
maxPoints: Number,
minPoints: Number,
freehand: Boolean,
wrapX: Boolean
}
*/
options: Object
},
watch: {
type() {
if (!this.manual) {
this.finish()
this.draw()
this.modify()
}
}
},
methods: {
getStyle(config) {
if (!config) return null
return typeof config === 'function'
? config()
: parseStyle(config)
},
init(map) {
if (this.layer) return
const source = new VectorSource()
const style = this.getStyle(this.effect)
this.layer = new VectorLayer({
source,
style
})
map.addLayer(this.layer)
if (!this.manual) {
this.draw()
this.modify()
}
this.$emit('ready', this)
setTimeout(() => {
// 设置画板图层在所有图层的最顶层(解决切换地图瓦片后编辑图层被覆盖bug)
this.layer.setZIndex(map.getLayers().getArray().length)
}, 100)
},
/**
* 进入绘画模式
* @method draw
* @param {function} [callback] 绘画结束时回调函数
*/
draw(callback) {
if (!this.layer) return
const source = this.layer.getSource()
const style = this.getStyle(this.brush)
const type = this.type
const map = this.myMap.map
const draw = new Draw({
...this.options,
type,
source,
style
})
this.drawStartHandler = e => {
/**
* 开始绘画时触发
* @event drawstart
* @param {Object} e 事件对象,{feature}
*/
this.$emit('drawstart', e)
}
this.drawEndHandler = e => {
callback && callback(e)
/**
* 结束绘画时触发
* @event drawend
* @param {Object} e 事件对象,{feature}
*/
this.$emit('drawend', e)
}
draw.on('drawstart', this.drawStartHandler)
draw.on('drawend', this.drawEndHandler)
this.drawInstance = draw
this.snapInstance = new Snap({source})
map.addInteraction(draw)
map.addInteraction(this.snapInstance)
},
/**
* 进入绘画编辑模式
* @method modify
* @param {function} [callback] 编辑结束时回调函数
*/
modify(callback, target) {
if (!this.layer) return
const map = this.myMap.map
let source = this.layer.getSource()
const style = this.getStyle(this.brush)
let features
if (target) {
source = null
features = target
}
const modify = new Modify({
...this.options,
features,
source,
style
});
this.modifyStartHandler = e => {
/**
* 开始编辑时触发
* @event modifystart
* @param {Object} e 事件对象,{feature}
*/
this.$emit('modifystart', e)
}
this.modifyEndHandler = e => {
callback && callback(e)
/**
* 结束编辑时触发
* @event modifyend
* @param {Object} e 事件对象,{feature}
*/
this.$emit('modifyend', e)
}
modify.on('modifystart', this.modifyStartHandler)
modify.on('modifyend', this.modifyEndHandler)
this.modifyInstance = modify
map.addInteraction(this.modifyInstance)
},
/**
* 完成绘画和编辑
* @method finish
*/
finish() {
const map = this.myMap.map
if (!map) return
const draw = this.drawInstance
const modify = this.modifyInstance
if (draw) {
draw.un('drawstart', this.drawStartHandler)
draw.un('drawend', this.drawEndHandler)
draw.dispose()
map.removeInteraction(draw)
map.removeInteraction(this.snapInstance)
this.drawInstance = null
}
if (modify) {
modify.un('modifystart', this.modifyStartHandler)
modify.un('modifyend', this.modifyEndHandler)
modify.dispose()
map.removeInteraction(modify)
this.modifyInstance = null
}
},
dispose() {
this.finish()
if (this.myMap.map) {
this.layer && this.myMap.map.removeLayer(this.layer)
}
},
/**
* 获取当前画布图层上的图形
* @method getFeatures
* @returns {Array}
*/
getFeatures() {
if (!this.layer) return []
const source = this.layer.getSource()
return source.getFeatures()
},
/**
* 清空画布
* @method clear
*/
clear() {
if (!this.layer) return
const source = this.layer.getSource()
source.clear()
},
/**
* 删除指定图形
* @method removeFeature
* @param feature
*/
removeFeature(feature) {
const source = this.layer.getSource()
source.removeFeature(feature)
},
/**
* 添加图形, 图形加入到矢量图层
* @method addFeature
* @param {Feature[]|feature} feature
*/
addFeature(feature) {
const features = [].concat(feature)
const source = this.layer.getSource()
source.addFeatures(features)
},
/**
* 图层上全部图形转换成JSON描述
* @returns {string}
*/
toJSON() {
const features = this.getFeatures()
return (new GeoJSON()).writeFeatures(features)
},
/**
* 根据GeoJSON在图层上创建 feature
* @param {object} json
*/
fromJSON(json) {
const features = (new GeoJSON()).readFeatures(json)
this.addFeature(features)
},
/**
* Feature转换成JSON
* @param {Object} feature
* @returns {string}
*/
writeFeature(feature) {
return (new GeoJSON()).writeFeature(feature)
},
/**
* JSON转换成Feature
* @param json
* @returns {string}
*/
readFeature(json) {
return (new GeoJSON()).writeFeature(json)
}
},
created() {
this.myMap.mapReady(this.init)
},
beforeDestroy() {
this.dispose()
}
}