import {define} from '/node_modules/vl-ui-core/dist/vl-core.js';
import {VlMapVectorLayer} from '/src/vl-map-vector-layer.js';
import {
OlVectorSource,
OlGeoJSON,
OlClusterSource,
OlPoint,
} from '/node_modules/vl-mapactions/dist/vl-mapactions.js';
/**
* VlMapFeaturesLayer
* @class
* @classdesc Deze kaartlaag staat je toe om een set van te tonen features in te stellen.
*
* @extends VlMapVectorLayer
*
* @property {boolean} data-vl-auto-extent - Attribuut geeft aan of er automatisch gezoomt wordt op de kaartlaag zodat al de features zichtbaar zijn.
* @property {number} data-vl-auto-extent-max-zoom - Attribuut geeft aan tot op welk niveau er maximaal automatisch gezoomd wordt bij een extent.
* @property {boolean} data-vl-cluster - Attribuut geeft aan of de features geclusterd moeten worden of niet.
* @property {number} data-vl-cluster-distance - Attribuut geeft aan vanaf welke afstand tussen features er geclusterd mag worden.
* @property {string[]} data-vl-features - Attribuut die de kaartlaag bevat.
*
* @see {@link https://www.github.com/milieuinfo/webcomponent-vl-ui-map/releases/latest|Release notes}
* @see {@link https://www.github.com/milieuinfo/webcomponent-vl-ui-map/issues|Issues}
* @see {@link https://webcomponenten.omgeving.vlaanderen.be/demo/vl-map-features-layer.html|Demo}
*/
export class VlMapFeaturesLayer extends VlMapVectorLayer {
static get _observedAttributes() {
return VlMapVectorLayer._observedAttributes.concat(['auto-extent', 'features']);
}
constructor() {
super();
this._geoJSON = new OlGeoJSON();
this._source = this.__createSource();
this._layer = this._createLayer();
}
async connectedCallback() {
await super.connectedCallback();
this._autoZoomToExtent();
}
/**
* Geeft de OpenLayers features collectie van de kaartlaag terug.
*
* @return {object}
*/
get features() {
return this.__featuresSource ? this.__featuresSource.getFeatures() : this._featuresFromAttribute;
}
get _featuresFromAttribute() {
const features = this.getAttribute('features');
return features ? this.__readGeoJsonFeatures(features) : [];
}
/**
* Zet de OpenLayers features collectie op de kaartlaag.
*
* @param {object} features
*/
set features(features) {
this.setAttribute('features', JSON.stringify(features));
}
get _autoExtent() {
return this.getAttribute('auto-extent') != undefined;
}
get _autoExtentMaxZoom() {
return this.getAttribute('auto-extent-max-zoom');
}
get cluster() {
return this.getAttribute('cluster') != undefined;
}
get _clusterDistance() {
return this.getAttribute('cluster-distance');
}
/**
* Verwijdert de stijl van al de kaartlaag features.
*/
removeFeaturesStyle() {
if (this.__featuresSource && this.__featuresSource.getFeatures()) {
this.__featuresSource.getFeatures().forEach((feature) => {
feature.setStyle(null);
});
}
}
/**
* Geeft de feature terug op basis van het id attribuut.
*
* @param {number} id
* @return {Object}
*/
getFeature(id) {
if (this.__featuresSource && this.__featuresSource.getFeatures()) {
return this.__featuresSource.getFeatures().filter((feature) => {
return feature.getId() === id;
})[0];
}
}
/**
* Geeft de cluster terug op basis van het id attribuut.
*
* @param {number} id
* @return {boolean}
*/
getCluster(id) {
if (this._layer) {
return this._layer.getSource().getFeatures().filter((cluster) => {
const features = cluster.get('features');
if (features) {
return features.some((feature) => {
return feature.getId() === id;
});
} else {
return false;
}
})[0];
}
}
/**
* Zoom naar alle features in deze layer.
*
* @param {number} maxZoom - Hoe diep er maximaal ingezoomd mag worden.
*/
async zoomToExtent(maxZoom) {
if (this.mapElement && this.boundingBox) {
this.mapElement.zoomTo(this.boundingBox, maxZoom);
}
}
/**
* Verwijdert alle features van de laag
*/
clearFeatures() {
if (this.__featuresSource) {
this.__featuresSource.clear();
this._featuresChanged();
}
}
/**
* Voegt een feature toe aan de kaartlaag via geojson
*
* @param {string} feature
*/
addFeature(feature) {
if (this.__featuresSource) {
this.__featuresSource.addFeatures([this._geoJSON.readFeature(feature)]);
this._featuresChanged();
}
}
/**
* Voegt een featurecollection toe aan de kaartlaag via geojson
*
* @param {string} featureCollection
*/
addFeatureCollection(featureCollection) {
if (this.__featuresSource) {
this.__featuresSource.addFeatures(this._geoJSON.readFeatures(featureCollection));
this._featuresChanged();
}
}
_autoExtentChangedCallback() {
this._autoZoomToExtent();
}
_featuresChangedCallback(oldValue, newValue) {
if (newValue && this._layer) {
this.__featuresSource.clear();
this.__featuresSource.addFeatures(this.__readGeoJsonFeatures(newValue));
this._featuresChanged();
}
}
_featuresChanged() {
this._autoZoomToExtent();
this.rerender();
}
_autoZoomToExtent() {
if (this._autoExtent) {
this.zoomToExtent(this._autoExtentMaxZoom);
}
}
get boundingBox() {
if (this.__featuresSource && this.__featuresSource.getFeatures().length > 0) {
return this.__featuresSource.getExtent();
}
}
__createSource() {
const source = new OlVectorSource({
features: this.features,
});
return this.cluster ? this.__createClusterSource(source) : source;
}
__createClusterSource(source) {
return new OlClusterSource({
distance: this._clusterDistance,
source: source,
geometryFunction: (feature) => {
const geometry = feature.getGeometry();
if (geometry instanceof OlPoint) {
return geometry;
} else {
return this.__ignoreClustering();
}
},
});
}
get __featuresSource() {
if (this.cluster && this.source) {
return this.source.getSource();
}
return this.source;
}
__ignoreClustering() {
return null;
}
__readGeoJsonFeatures(value) {
return this._geoJSON.readFeatures(value);
}
}
define('vl-map-features-layer', VlMapFeaturesLayer);