import { Layer } from "../Layer/Layer.js";
import { saveAsFile } from "../../../utils/utils.js";
import { GeoJSONLayerProxy } from "./GeoJSONLayer.proxy.js";
import { GeoJSONLayerProxyLeaflet } from "./GeoJSONLayer.proxy.leaflet.js";
import { EventManager } from "../../../events/EventManager.js";
import { GeoJSONLayerSchema } from './GeoJSONLayer.schema.js';
export { GeoJSONLayer }
/**
* GeoJSON Layer Implementation
*
* @author rhess <robin.hess@awi.de>
* @memberof vef.map.layer
*/
class GeoJSONLayer extends Layer {
/**
* Set all properties for the layer based on the options object.
*
* @param {object} config
* @param {object} cache
* @param {string} id
*/
constructor(config, cache, id) {
// calling parent constructor
super(config, cache, id);
this.setSchema_(GeoJSONLayerSchema.getSchema());
// framework specific map implementations
this.layerProxies_.leaflet = GeoJSONLayerProxyLeaflet;
this.activeLayer_ = new GeoJSONLayerProxy();
this.previousActiveLayer_ = null;
}
/**
* create a map layer based on the service options
*
* @param {string} type e.g. "leaflet"
* @private
*/
createMapLayer_(type, options) {
const proxy = super.createMapLayer_(type, this);
if (proxy) {
proxy.on("layerproxy_click", (e) => this.fire("layer_click", e));
proxy.on("layerproxy_mouseover", (e) => this.fire("layer_mouseover", e));
proxy.on("layerproxy_mouseout", (e) => this.fire("layer_mouseout", e));
}
return proxy;
}
/**
* Helper method to update the mapLayer according to
* the current state. Might be necessary after switching the map type
*
* @private
*/
updateMapLayer_(type) {
// init the event callbacks for the buttons in the popup
if (this.editingEnabled && (this.popupEvents_.length == 0)) this.initPopupEvents_();
if (this.activeLayer_ !== this.previousActiveLayer_) {
this.activeLayer_.setData(this.geoJSON);
}
this.previousActiveLayer_ = this.activeLayer_;
}
setData(geoJson) {
this.geoJSON = {
type: "FeatureCollection",
features: []
};
if (typeof geoJson == "string") {
fetch(geoJson).then(response => response.json()).then(json => {
this.geoJSON = json;
this.activeLayer_.setData(this.geoJSON);
})
} else if (typeof geoJson == "object") {
this.geoJSON = geoJson;
} else {
console.warn("Invalid or missing GeoJSON");
}
this.activeLayer_.setData(this.geoJSON);
}
/**
* Set label of a feature
* @param {object} feature
* @param {string} label
*/
setLabel(feature, label) {
feature.properties.label = label;
this.activeLayer_.updateTooltips(feature);
}
bringToFront() {
this.activeLayer_.bringToFront();
}
bringToBack() {
this.activeLayer_.bringToBack();
}
/**
* Set color of a feature
* @param {object} feature
* @param {string} color
*/
setColor(feature, color) {
feature.properties.color = color;
this.activeLayer_.updateStyle();
}
/**
* init the event callbacks for the buttons in the popup
* @private
*/
initPopupEvents_() {
let editing = false;
this.popupEvents_ = [
{
title: "<i class='fas fa-draw-polygon'></i><br/>edit shape",
callback: e => {
if (editing) {
this.stopEditing_(e.content.feature);
} else {
this.startEditing_(e.content.feature);
}
editing = !editing;
},
toggleMode: true,
isEnabled: () => { return editing },
width: "33%"
},
{
title: "<i class='fas fa-download'></i><br/>export",
callback: e => this.exportGeometry("download"),
width: "34%"
},
{
title: "<i class='fas fa-trash'></i><br/>remove",
callback: e => this.fire("layer_request_remove", this),
width: "33%"
}
];
}
/**
* start editing for a vector based layer
* @private
*/
startEditing_(feature) {
this.activeLayer_.startEditing(feature);
}
/**
* stop editing for a vector based layer
* @private
*/
stopEditing_(feature) {
this.activeLayer_.stopEditing(feature);
this.geoJSON = this.activeLayer_.getGeoJson();
if (!("properties" in this.geoJSON)) this.geoJSON.properties = {};
if (!("title" in this.geoJSON.properties)) this.geoJSON.properties.title = this.title;
this.activeLayer_.setData(this.geoJSON);
EventManager.fire("close_map_popup", {});
}
/**
* Trigger a file download containing the geometry as a geojson file
*
* @param {string} mode supported values: "string", "object", "download" (default)
*/
exportGeometry(mode) {
// only export first feature, if only one feature exists
let geoJSON = this.geoJSON;
if (("features" in geoJSON) && (geoJSON.features.length == 1)) geoJSON = geoJSON.features[0];
if (mode == "object") return this.geoJSON;
const jsonString = JSON.stringify(this.geoJSON);
if (mode == "string") return jsonString
const blob = new Blob([jsonString], { type: "text/plain;charset=utf-8" });
saveAsFile(blob, this.title + ".json");
}
/**
* Get Info of the last clicked features
* @returns {Promise} feature info
*/
getFeatureInfo() {
return new Promise(resolve => {
resolve(this.activeLayer_.getClickedFeatures());
});
}
/**
* Set the transparency between 0 and 1
* @param {number} opacity
*/
setOpacity(opacity) {
this.opacity = opacity;
this.activeLayer_.updateStyle();
}
/**
* Get the bounding box as an object
* @returns {object} { min: {x, y}, max: {x, y}, crs: "CRS:84" }
*/
getBounds() {
const bounds = this.activeLayer_.getBounds();
return (bounds) ? bounds : super.getBounds();
}
}