wangbd-myui
Version:
MY前端基础框架核心组件库
226 lines (221 loc) • 6.36 kB
JavaScript
/**
* GeoJSON 图层组件
* @module $ui/map/my-map-geo
*/
import GeoJSON from 'ol/format/GeoJSON'
import {Vector as VectorLayer} from 'ol/layer';
import {Vector as VectorSource} from 'ol/source'
import styleMixin from '../../mixins/style'
import {geoJsonDecode} from '$ui/map/utils/util'
import parseStyle from '$ui/map/utils/style'
import LineString from 'ol/geom/LineString'
// 样式构造函数
const defaultStyleCreator = vm => {
const {stroke, text, fill, styleText, showText} = vm
return feature => {
const name = feature.get('name')
let content = null
if (showText) {
content = text ? {text: name, ...styleText} : {text: name, font: '12px'}
}
return parseStyle({
stroke,
fill,
text: content
})
}
}
// 多维数组转二维数组
const flatCoords = function (coords, arr = []) {
let flag = false
for (let index = 0; index < coords.length; index++) {
if (coords[index][0] && typeof coords[index][0] === 'object') {
flag = true
}
}
if (flag) {
const newCoords = coords.reduce((total, item) => {
total = total.concat(item)
return total
}, [])
flatCoords(newCoords, arr)
} else {
coords.forEach((coord) => {
arr.push(coord)
})
}
return arr
}
export default {
name: 'MyMapGeo',
mixins: [styleMixin],
inject: ['myMap'],
render() {
return null
},
/**
* 属性参数
* @property {Number} [zIndex] 显示层级
* @property {String} [fill] 填充颜色
* @property {Object} [stroke] 描边 {color,lineCap, lineJoin, lineDash, lineDashOffset, miterLimit, width}
* @property {Object} [text] 文本, {font,maxAngle,offsetX,offsetY,overflow,placement,scale,rotateWithView,rotation,text,textAlign,textBaseline,fill,stroke,backgroundFill,backgroundStroke,padding}
* @property {Function} [styleFunction] 渲染Style函数,必须返回Style实例
* @property {Object} [json] GeoJSON 数据
* @property {Object|Function} [hoverStyle] 鼠标经过时的样式
*/
props: {
json: Object,
hoverStyle: [Object, Function],
// 显示文本
showText: {
type: Boolean,
default: true
}
},
methods: {
init(map) {
if (this.layer) return
const source = new VectorSource({})
const style = typeof this.styleFunction === 'function'
? this.styleFunction
: defaultStyleCreator(this)
this.layer = new VectorLayer({
zIndex: this.zIndex,
source,
style
})
map.addLayer(this.layer)
this.draw(this.json)
/**
* 初始化完成时触发
* @event ready
*/
this.$emit('ready', this)
},
dispose() {
if (this.myMap && this.myMap.map && this.layer) {
this.clear()
this.myMap.map.removeLayer(this.layer)
}
},
/**
* 绘制图形,当json数据发生改变时,需要调用该方法重绘
* @param {object} json
*/
draw(json) {
if (!json || !this.layer) return
this.clear()
const geoJson = geoJsonDecode(json)
let features = new GeoJSON().readFeatures(geoJson) || []
features = features.map(feature => {
feature.__vm__ = this
return feature
})
const source = this.layer.getSource()
source.addFeatures(features)
},
/**
* 清除图形
*/
clear() {
if (!this.layer) {
const source = this.layer.getSource()
source.clear()
}
},
/**
* 获取全部图形
* @return {array}
*/
getFeatures() {
if (!this.layer) return []
const source = this.layer.getSource()
return source.getFeatures()
},
/**
* 根据名称获取 Feature
* @param {string} name
* @return {Feature}
*/
getFeature(name) {
const features = this.getFeatures()
return features.find(f => f.get('name') === name)
},
/**
* 获取图形区域名称与经纬度映射
* @return {Object}
*/
getCoordinates() {
const features = this.getFeatures()
const coordinates = Object.create(null)
features.forEach(f => {
const name = f.get('name')
coordinates[name] = f.get('cp')
})
return coordinates
},
/**
* 获取图形区域extent(ol/extent)
* @return {Array}
*/
getExtent() {
const features = this.getFeatures()
const featuresCoords = features.map((feature) => {
return feature.getGeometry().getCoordinates()
})
const arr = featuresCoords.reduce((total, coords) => {
const arr = flatCoords(coords, [])
total = total.concat(arr)
return total
}, [])
const fullGeo = new LineString(arr)
const extent = fullGeo.getExtent()
return extent
},
/**
* 继承鼠标经过设置图形的层级和文本字体
* @param feature
* @param style
*/
syncStyle(feature, style) {
if (!this.layer) return null
const zIndex = this.zIndex || 1 + 1
style.setZIndex(zIndex)
if (!this.showText) return
const styleFunction = this.layer.getStyle()
const featureStyle = styleFunction(feature)
const styleText = featureStyle.getText()
if (!styleText) return
const content = styleText.getText()
const font = styleText.getFont()
const text = style.getText()
if (content && text) {
text.setText(content)
text.setFont(font)
}
},
handleMouseEnter(e, feature) {
if (!this.layer) return
const style = typeof this.hoverStyle === 'function'
? this.hoverStyle()
: parseStyle(this.hoverStyle)
this.syncStyle(feature, style)
feature.setStyle(style)
},
handleMouseLeave(e, feature) {
if (!this.layer) return
feature.setStyle(null)
}
},
created() {
this.myMap.mapReady(this.init)
if (this.hoverStyle) {
this.$on('mouseenter', this.handleMouseEnter)
this.$on('mouseleave', this.handleMouseLeave)
}
},
beforeDestroy() {
this.dispose()
this.$off()
}
}