tchen-vuelayers
Version:
Web map Vue components with the power of OpenLayers
167 lines (157 loc) • 4.83 kB
JavaScript
import Vue from 'vue'
import { warn } from '../util/log'
import { isFunction, reduce } from '../util/minilo'
export default {
created () {
/**
* @type {Style[]|StyleFunction|Vue|undefined}
* @private
*/
this._styles = undefined
},
methods: {
/**
* Default style factory
* @return {Style[]|StyleFunction|undefined}
* @protected
*/
getDefaultStyles () {},
/**
* @returns {Object}
* @protected
*/
getServices () {
const vm = this
return {
get stylesContainer () { return vm },
}
},
/**
* @return {Style[]|StyleFunction|Vue|undefined}
*/
getStyles () {
return this._styles
},
/**
* @param {Style|StyleFunction|Vue|undefined} style
* @return {void}
*/
addStyle (style) {
let currentStyles = this.getStyles()
let olStyle = style instanceof Vue ? style.$style : style
if (isFunction(olStyle)) {
if (process.env.NODE_ENV !== 'production' && currentStyles) {
warn('Component already has style components among it\'s descendants. ' +
'Avoid use of multiple vl-style-func or combining vl-style-func with vl-style-box on the same level')
}
currentStyles = style
} else {
if (!Array.isArray(currentStyles)) {
if (process.env.NODE_ENV !== 'production' && currentStyles) {
warn('Component already has style components among it\'s descendants. ' +
'Avoid use of multiple vl-style-func or combining vl-style-func with vl-style-box on the same level')
}
currentStyles = []
}
style = style instanceof Vue ? style : { $style: style, condition: true }
if (!currentStyles.includes(style)) {
currentStyles.push(style)
}
}
this.setStyle(currentStyles)
},
/**
* @param {Array<{style: Style, condition: (function|boolean|undefined)}>|StyleFunction|Vue|undefined} styles
* @return {void}
*/
setStyle (styles) {
if (styles === this._styles) return
this._styles = styles
const styleTarget = this.getStyleTarget()
if (!styleTarget) return
if (this._styles === null || this._styles) {
styleTarget.setStyle(this.createStyleFunc())
} else {
styleTarget.setStyle(undefined)
}
},
/**
* @param {Style|StyleFunction|Vue|undefined} style
* @return {void}
*/
removeStyle (style) {
let currentStyles = this.getStyles()
if (currentStyles === style) {
currentStyles = undefined
} else if (Array.isArray(currentStyles)) {
currentStyles = currentStyles.filter(s => {
return style instanceof Vue
? s !== style
: s.$style !== style
})
currentStyles.length || (currentStyles = undefined)
}
this.setStyle(currentStyles)
},
/**
* Returns OL object that can be styled (i.e. has setStyle/getStyle methods) or undefined
* @return {*}
* @protected
* @abstract
*/
getStyleTarget () {
throw new Error('Not implemented method')
},
/**
* Style function factory
* @returns {StyleFunction}
* @protected
*/
createStyleFunc () {
const vm = this
const defaultStyles = this.getDefaultStyles()
return function __styleTargetStyleFunc (feature, resolution) {
if (!feature.getGeometry()) return
let styles = vm.getStyles()
/* eslint-disable brace-style */
// handle provided styles
// styles - StyleFunction or vl-style-func
if (styles && (isFunction(styles) || isFunction(styles.$style))) {
let styleFunc = isFunction(styles) ? styles : styles.$style
styles = styleFunc(feature, resolution)
}
// styles is array of { $style: Style, condition: (bool|function():bool) }
else if (Array.isArray(styles)) {
styles = reduce(styles, (newStyles, { $style, condition }) => {
if (
condition == null ||
(condition === true) ||
(
isFunction(condition) &&
condition(feature, resolution)
)
) {
newStyles.push($style)
}
return newStyles
}, [])
}
/* eslint-enable brace-style */
// not empty or null style
if (
styles === null ||
(Array.isArray(styles) && styles.length)
) {
return styles
}
// fallback to default style
styles = defaultStyles
if (styles) {
return isFunction(styles)
? styles(feature, resolution)
: styles
}
}
},
},
}