tchen-vuelayers
Version:
Web map Vue components with the power of OpenLayers
392 lines (352 loc) • 12.2 kB
JavaScript
/**
* VueLayers
* Web map Vue components with the power of OpenLayers
*
* @package vuelayers
* @author Vladimir Vershinin <ghettovoice@gmail.com>
* @version 0.11.1
* @license MIT
* @copyright (c) 2017-2019, Vladimir Vershinin <ghettovoice@gmail.com>
*/
import _Object$assign from '@babel/runtime-corejs2/core-js/object/assign';
import _objectSpread from '@babel/runtime-corejs2/helpers/esm/objectSpread';
import _Object$keys from '@babel/runtime-corejs2/core-js/object/keys';
import _Array$isArray from '@babel/runtime-corejs2/core-js/array/is-array';
import Circle from 'ol/style/Circle';
import Fill from 'ol/style/Fill';
import Icon from 'ol/style/Icon';
import ImageStyle from 'ol/style/Image';
import RegularShape from 'ol/style/RegularShape';
import Stroke from 'ol/style/Stroke';
import Style from 'ol/style/Style';
import Text from 'ol/style/Text';
import parseColor from 'parse-color';
import { isFunction, isNumeric, lowerFirst, pick, reduce, upperFirst } from '../util/minilo';
import { GEOMETRY_TYPE } from './consts';
import * as geomHelper from './geom';
/**
* @return {VlStyle[]}
*/
function defaultStyle() {
return [{
fillColor: [255, 255, 255, 0.4],
strokeColor: '#3399CC',
strokeWidth: 1.25,
imageRadius: 5
}];
}
/**
* @return {Object<GEOMETRY_TYPE, VlStyle[]>}
*/
function defaultEditStyle() {
/** @type {Object<GEOMETRY_TYPE, VlStyle[]>} */
var styles = {};
var white = [255, 255, 255, 1];
var blue = [0, 153, 255, 1];
var width = 3;
styles[GEOMETRY_TYPE.LINE_STRING] = [{
strokeColor: white,
strokeWidth: width + 2
}, {
strokeColor: blue,
strokeWidth: width
}];
styles[GEOMETRY_TYPE.MULTI_LINE_STRING] = styles[GEOMETRY_TYPE.LINE_STRING];
styles[GEOMETRY_TYPE.POLYGON] = [{
fillColor: [255, 255, 255, 0.5]
}].concat(styles[GEOMETRY_TYPE.LINE_STRING]);
styles[GEOMETRY_TYPE.MULTI_POLYGON] = styles[GEOMETRY_TYPE.POLYGON];
styles[GEOMETRY_TYPE.CIRCLE] = styles[GEOMETRY_TYPE.POLYGON].concat(styles[GEOMETRY_TYPE.LINE_STRING]);
styles[GEOMETRY_TYPE.POINT] = [{
imageRadius: width * 2,
fillColor: blue,
strokeColor: white,
strokeWidth: width / 2,
zIndex: Infinity
}];
styles[GEOMETRY_TYPE.MULTI_POINT] = styles[GEOMETRY_TYPE.POINT];
styles[GEOMETRY_TYPE.GEOMETRY_COLLECTION] = styles[GEOMETRY_TYPE.POLYGON].concat(styles[GEOMETRY_TYPE.LINE_STRING], styles[GEOMETRY_TYPE.POINT]);
return styles;
}
var isEmpty = function isEmpty(x) {
if (x == null) return true;
if (typeof x === 'number') return false;
return (typeof x === 'string' || _Array$isArray(x)) && !x.length || !_Object$keys(x).length;
};
/**
* @param {VlStyle} vlStyle
* @return {Style|undefined}
*/
function createStyle(vlStyle) {
if (isEmpty(vlStyle)) return;
var olStyle = {
text: createTextStyle(vlStyle),
fill: createFillStyle(vlStyle),
stroke: createStrokeStyle(vlStyle),
image: createImageStyle(vlStyle),
geometry: createGeomStyle(vlStyle),
zIndex: vlStyle.zIndex
};
if (!isEmpty(olStyle)) {
return new Style(olStyle);
}
}
var addPrefix = function addPrefix(prefix) {
return function (str) {
return prefix + (prefix ? upperFirst(str) : str);
};
};
/**
* @param {*} color
* @returns {*}
*/
function normalizeColor(color) {
var c = color;
if (typeof color === 'string') {
c = parseColor(color).rgba;
}
return c;
}
/**
* @param {VlStyle} vlStyle
* @param {string} [prefix]
* @returns {Fill|undefined}
*/
function createFillStyle(vlStyle) {
var prefix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
var prefixKey = addPrefix(prefix);
var keys = ['fillColor'].map(prefixKey);
var compiledKey = prefixKey('fill'); // check on already compiled style existence
if (vlStyle[compiledKey] instanceof Fill) return vlStyle[compiledKey];
var fillStyle = reduce(vlStyle, function (style, value, name) {
if (keys.includes(name) === false) {
return style;
}
name = lowerFirst(name.replace(new RegExp(prefixKey('fill')), ''));
if (name === 'color') {
value = normalizeColor(value);
}
style[name] = value;
return style;
}, {});
if (!isEmpty(fillStyle)) {
return new Fill(fillStyle);
}
}
/**
* @param {VlStyle} vlStyle
* @param {string} [prefix]
* @returns {Stroke|undefined}
*/
function createStrokeStyle(vlStyle) {
var prefix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
var prefixKey = addPrefix(prefix);
var keys = ['strokeColor', 'strokeWidth', 'strokeDash', 'strokeCap', 'strokeJoin'].map(prefixKey);
var compiledKey = prefixKey('stroke');
if (vlStyle[compiledKey] instanceof Stroke) return vlStyle[compiledKey];
var strokeStyle = reduce(vlStyle, function (style, value, name) {
if (keys.includes(name) === false) {
return style;
}
switch (name) {
case prefixKey('strokeColor'):
case prefixKey('strokeWidth'):
name = lowerFirst(name.replace(new RegExp(prefixKey('stroke')), ''));
break;
case prefixKey('strokeDash'):
case prefixKey('strokeCap'):
case prefixKey('strokeJoin'):
name = 'line' + name.replace(new RegExp(prefixKey('stroke')), '');
break;
}
if (name === 'color') {
value = normalizeColor(value);
}
style[name] = value;
return style;
}, {});
if (!isEmpty(strokeStyle)) {
return new Stroke(strokeStyle);
}
}
/**
* @param {VlStyle} vlStyle
* @returns {Image|undefined}
* @todo split to separate circle, regShape, Icon
*/
function createImageStyle(vlStyle) {
if (isEmpty(vlStyle.imageSrc) && isEmpty(vlStyle.image) && isEmpty(vlStyle.imagePoints) && !isNumeric(vlStyle.imageRadius)) {
return;
}
if (vlStyle.image instanceof ImageStyle) return vlStyle.image;
var imageStyle, Ctor;
if (!isEmpty(vlStyle.imageSrc) || !isEmpty(vlStyle.image)) {
// icon construction
Ctor = Icon; // then create Icon options
imageStyle = _objectSpread({}, vlStyle, {
anchor: vlStyle.imageAnchor,
anchorOrigin: vlStyle.imageAnchorOrigin,
color: vlStyle.imageColor,
offset: vlStyle.imageOffset,
offsetOrigin: vlStyle.imageOffsetOrigin,
opacity: vlStyle.imageOpacity,
scale: vlStyle.imageScale,
rotation: vlStyle.imageRotation,
size: vlStyle.imageSize,
img: vlStyle.image,
imgSize: vlStyle.imageImgSize,
src: vlStyle.imageSrc,
crossOrigin: vlStyle.imageCrossOrigin
});
} else if (vlStyle.imagePoints != null) {
// regular shape construction
Ctor = RegularShape; // create RegularShape options
imageStyle = _objectSpread({}, vlStyle, {
points: vlStyle.imagePoints,
radius: vlStyle.imageRadius,
radius1: vlStyle.imageRadius1,
radius2: vlStyle.imageRadius2,
angle: vlStyle.imageAngle,
rotation: vlStyle.imageRotation
});
} else {
// circle construction
Ctor = Circle; // create Circle options
imageStyle = _objectSpread({}, vlStyle, {
radius: vlStyle.imageRadius
});
}
imageStyle = _objectSpread({}, imageStyle, {
fill: createFillStyle(vlStyle, 'image') || createFillStyle(vlStyle),
stroke: createStrokeStyle(vlStyle, 'image') || createStrokeStyle(vlStyle),
snapToPixel: true
});
if (!isEmpty(imageStyle)) {
return new Ctor(imageStyle);
}
}
/**
* @param {VlStyle} vlStyle
* @returns {Text|undefined}
*/
function createTextStyle(vlStyle) {
// noinspection JSValidateTypes
if (vlStyle.text == null) return;
if (vlStyle.text instanceof Text) return vlStyle.text;
var textStyle = {
text: vlStyle.text
};
var fontSize = vlStyle.textFontSize ? vlStyle.textFontSize + 'px' : undefined;
var font = ['normal', fontSize, vlStyle.textFont].filter(function (x) {
return !!x;
}).join(' ');
_Object$assign(textStyle, pick(['textAlign', 'textBaseline'], vlStyle), {
font: font,
fill: createFillStyle(vlStyle, 'text') || createFillStyle(vlStyle),
stroke: createStrokeStyle(vlStyle, 'text') || createStrokeStyle(vlStyle),
scale: vlStyle.textScale,
rotation: vlStyle.textRotation,
offsetX: vlStyle.textOffsetX,
offsetY: vlStyle.textOffsetY,
rotateWithView: vlStyle.textRotateWithView,
padding: vlStyle.textPadding,
maxAngle: vlStyle.textMaxAngle,
overflow: vlStyle.textOverflow,
placement: vlStyle.textPlacement,
backgroundFill: createFillStyle(vlStyle, 'textBackground'),
backgroundStroke: createStrokeStyle(vlStyle, 'textBackground')
});
if (!isEmpty(textStyle)) {
return new Text(textStyle);
}
}
/**
* @param {VlStyle} vlStyle
* @return {Geometry|function|undefined}
*/
function createGeomStyle(vlStyle) {
if (isFunction(vlStyle.geom)) {
return function __styleGeomFunc(feature) {
return vlStyle.geom(feature, geomHelper);
};
}
return vlStyle.geom;
}
/**
* @typedef {Style|Image|Fill|Stroke|Text|StyleFunction} OlStyle
*/
/**
* @typedef {Object} VlStyle
*
* Shared
* @property {string|number[]|undefined} fillColor
* @property {string|number[]|undefined} strokeColor
* @property {number|undefined} strokeWidth
* @property {number[]|undefined} strokeDash
* @property {string|undefined} strokeCap
* @property {string|undefined} strokeJoin
* @property {number|undefined} zIndex
* @property {Fill|undefined} fill
* @property {Stroke|undefined} stroke
*
* Text only
* @property {string|Text|undefined} text
* @property {string|undefined} textFont
* @property {number|undefined} textFontSize
* @property {string|number[]|undefined} textFillColor
* @property {string|number[]|undefined} textStrokeColor
* @property {number|undefined} textStrokeWidth
* @property {number[]|undefined} textStrokeDash
* @property {string|undefined} textStrokeCap
* @property {string|undefined} textStrokeJoin
* @property {number|undefined} textScale
* @property {string|undefined} textAlign
* @property {number|undefined} textRotation
* @property {number|undefined} textOffsetX
* @property {number|undefined} textOffsetY
* @property {Stroke|undefined} textStroke
* @property {Fill|undefined} textFill
* @property {boolean|undefined} textRotateWithView
* @property {number[]|undefined} textPadding
* @property {number|undefined} textMaxAngle
* @property {boolean|undefined} textOverflow
* @property {string|undefined} textPlacement
* @property {string|undefined} textBaseline
* @property {Fill|undefined} textBackgroundFillColor
* @property {Stroke|undefined} textBackgroundStrokeColor
* @property {Stroke|undefined} textBackgroundStrokeWidth
* @property {Stroke|undefined} textBackgroundStrokeDash
* @property {Stroke|undefined} textBackgroundStrokeCap
* @property {Stroke|undefined} textBackgroundStrokeJoin
*
* Image only
* @property {Image|undefined} image
* @property {string|undefined} imageSrc
* @property {number[]|undefined} imageSize
* @property {number[]|undefined} imageImgSize
* @property {number|undefined} imageOffset
* @property {number[]|undefined} imageAnchor
* @property {number|undefined} imageScale
* @property {number|undefined} imageRotation
* @property {number|undefined} imageRadius
* @property {number|undefined} imageRadius1
* @property {number|undefined} imageRadius2
* @property {number|undefined} imagePoints
* @property {number|undefined} imageAngle
* @property {number|undefined} imageOpacity
* @property {string|number[]|undefined} imageFillColor
* @property {string|number[]|undefined} imageStrokeColor
* @property {number|undefined} imageStrokeWidth
* @property {number[]|undefined} imageStrokeDash
* @property {string|undefined} imageStrokeCap
* @property {string|undefined} imageStrokeJoin
* @property {IconOrigin|undefined} imageAnchorOrigin
* @property {ColorLike|undefined} imageColor
* @property {IconOrigin|undefined} imageOffsetOrigin
* @property {Stroke|undefined} imageStroke
* @property {Fill|undefined} imageFill
* @property {string|undefined} imageCrossOrigin
*
* @property {Geometry|function|undefined} geom Coordinates should be in map projection
*/
export { defaultStyle, defaultEditStyle, createStyle, normalizeColor, createFillStyle, createStrokeStyle, createImageStyle, createTextStyle, createGeomStyle };