import color from 'ol/color';
import Style from 'ol/style/style';
import Circle from 'ol/style/circle';
import Fill from 'ol/style/fill';
import Stroke from 'ol/style/stroke';
import OverlayLayer from './overlay-layer';
import styleVariables from '../../styles/_variables.scss';
/**
* Vector Layer
* @extends OverlayLayer
*/
class VectorLayer extends OverlayLayer {
/**
* @param {Object} config - Configuration object
* @param {String} [config.title='OverlayLayer'] - Layer title
* @param {Boolean} [config.visible=false] - Layer initial status
* @param {String} config.server - URL of map server
* @param {String} config.layerName - Name of layer to display
* @param {String} [config.attribution=''] - Layer data attribution
* @param {Boolean} [config.exclusive=false] - If true, when the layer is shown, all other overlay layers are hidden
* @param {Object} config.style - Style configuration
* @param {String} config.style.property - Property that defines the style to use
* @param {Object} config.style.values - Object with possible valuesand their corresponding style
* @param {Object} [config.style.minRadius=3] - Mininum radius to use for feature style
* @param {Object} [config.style.maxRadius=10] - Maximum radius to use for feature style
* @param {Object[]} [config.popup] - Data to show when user clicks on a feature in the map
* @param {String|String[]} [config.popup[].property] - Name of field or array of fields names to show
* @param {String} [config.popup[].title] - Text to show as title
* @param {Function} [config.popup[].format] - Function to process field or fields value
* @param {Filter[]} [config.filters] - Set of filters to apply to the layer. Overrides global dashboard filters.
* @param {Object} [config.layerParams] - Extra params for OpenLayers Layer constructor
* @param {Object} [config.sourceParams] - Extra params for OpenLayers Source constructor
*/
constructor(Vector, config = {}) {
super(config);
config.style = config.style || {};
config.style.minRadius = config.style.minRadius || 3;
config.style.maxRadius = config.style.maxRadius || 10;
this.styleCache = {};
this.style = config.style;
this.popup = config.popup || [];
this.layer = new Vector(Object.assign({
title: this.title,
visible: this.visible,
exclusive: this.exclusive,
}, this.layerParams));
this.layer.setStyle(this.setStyle.bind(this));
this.layer.popup = config.popup;
}
/**
* Reloads layer data using current filters
*/
refresh() {
this.source.clear();
}
/**
* Sets feature style
* @param {Object} feature - Openlayers' [feature](https://openlayers.org/en/latest/apidoc/ol.Feature.html) object
* @param {Number} resolution - Current map resolution
* @returns {Object} - Openlayers' [style](https://openlayers.org/en/latest/apidoc/ol.style.Style.html) object
* @private
*/
setStyle(feature, resolution) {
const value = feature.get(this.style.property);
if (!value || !this.style.values[value]) {
return this.style.defaultStyle || this.buildDefaultStyle();
}
if (!this.styleCache[value]) {
this.styleCache[value] = {};
}
if (!this.styleCache[value][resolution]) {
const radius = Math.min(
Math.max(
this.style.minRadius,
Math.ceil(this.style.maxRadius / Math.log(Math.ceil(resolution))),
),
this.style.maxRadius,
);
this.styleCache[value][resolution] = new Style({
image: new Circle({
fill: new Fill({
color: color.asArray(this.style.values[value].color),
}),
radius,
stroke: this.buildDefaultStroke(),
}),
});
}
return [this.styleCache[value][resolution]];
}
/**
* Builds default stroke style
* @returns {Object} Openlayers' [Stroke](https://openlayers.org/en/latest/apidoc/ol.style.Stroke.html) object
* @private
*/
buildDefaultStroke() {
if (!this.defaultStroke) {
this.defaultStroke = new Stroke({
color: styleVariables.primaryColor,
width: 1,
});
}
return this.defaultStroke;
}
/**
* Builds default fill style
* @returns {Object} Openlayers' [Fill](https://openlayers.org/en/latest/apidoc/ol.style.Fill.html) object
* @private
*/
buildDefaultFill() {
if (!this.defaultFill) {
this.defaultFill = new Fill({
color: styleVariables.primaryColor,
});
}
return this.defaultFill;
}
/**
* Builds default style
* @returns {Object} Openlayers' [Style](https://openlayers.org/en/latest/apidoc/ol.style.Style.html) object
* @private
*/
buildDefaultStyle() {
if (!this.defaultStyle) {
this.defaultStyle = new Style({
fill: this.buildDefaultFill(),
stroke: this.buildDefaultStroke(),
image: new Circle({
fill: this.buildDefaultFill(),
radius: this.style.minRadius,
stroke: this.buildDefaultStroke(),
}),
});
}
return [this.defaultStyle];
}
}
export default VectorLayer;