Mercurial > gemma
view client/src/store/map.js @ 3151:47453337c698
client: gauges: set zoom level after selecting a gauge
author | Markus Kottlaender <markus@intevation.de> |
---|---|
date | Fri, 03 May 2019 13:36:31 +0200 |
parents | a69a8deb56fe |
children | fc008b32c593 |
line wrap: on
line source
/* This is Free Software under GNU Affero General Public License v >= 3.0 * without warranty, see README.md and license for details. * * SPDX-License-Identifier: AGPL-3.0-or-later * License-Filename: LICENSES/AGPL-3.0.txt * * Copyright (C) 2018, 2019 by via donau * – Österreichische Wasserstraßen-Gesellschaft mbH * Software engineering by Intevation GmbH * * Author(s): * * Bernhard Reiter <bernhard.reiter@intevation.de> * * Markus Kottländer <markus@intevation.de> * * Thomas Junk <thomas.junk@intevation.de> */ import Draw from "ol/interaction/Draw"; import { Stroke, Style, Fill, Circle } from "ol/style"; import { fromLonLat } from "ol/proj"; import { getLength, getArea } from "ol/sphere"; import { getCenter } from "ol/extent"; import { transformExtent } from "ol/proj"; import bbox from "@turf/bbox"; import app from "@/main"; import { HTTP } from "@/lib/http"; import Feature from "ol/Feature"; import Point from "ol/geom/Point"; // initial state const init = () => { return { openLayersMaps: [], syncedMaps: [], syncedView: null, initialLoad: true, extent: { lat: 6155376, lon: 1819178, zoom: 11 }, identifiedFeatures: [], // map features identified by clicking on the map currentMeasurement: null, // distance or area from line-/polygon-/cutTool lineToolEnabled: false, polygonToolEnabled: false, cutToolEnabled: false, isolinesLegendImgDataURL: "", differencesLegendImgDataURL: "" }; }; export default { init, namespaced: true, state: init(), getters: { openLayersMap: state => id => { return state.openLayersMaps.find( map => map.getTarget() === "map-" + (id || "main") ); }, filteredIdentifiedFeatures: state => { return state.identifiedFeatures.filter(f => f.getId()); } }, mutations: { initialLoad: (state, initialLoad) => { state.initialLoad = initialLoad; }, extent: (state, extent) => { state.extent = extent; }, addOpenLayersMap: (state, map) => { state.openLayersMaps.push(map); }, removeOpenLayersMap: (state, map) => { let index = state.openLayersMaps.findIndex( m => m.getTarget() === map.getTarget() ); if (index !== -1) { state.openLayersMaps.splice(index, 1); } }, syncedMaps: (state, ids) => { state.syncedMaps = ids; }, syncedView: (state, view) => { state.syncedView = view; }, setIdentifiedFeatures: (state, identifiedFeatures) => { state.identifiedFeatures = identifiedFeatures; }, addIdentifiedFeatures: (state, identifiedFeatures) => { state.identifiedFeatures = state.identifiedFeatures.concat( identifiedFeatures ); }, setCurrentMeasurement: (state, measurement) => { state.currentMeasurement = measurement; }, lineToolEnabled: (state, enabled) => { state.lineToolEnabled = enabled; state.openLayersMaps.forEach(m => { let tool = m .getInteractions() .getArray() .find(i => i.get("id") === "linetool"); if (tool) { tool.setActive(enabled); } }); }, polygonToolEnabled: (state, enabled) => { state.polygonToolEnabled = enabled; state.openLayersMaps.forEach(m => { let tool = m .getInteractions() .getArray() .find(i => i.get("id") === "polygontool"); if (tool) { tool.setActive(enabled); } }); }, cutToolEnabled: (state, enabled) => { state.cutToolEnabled = enabled; state.openLayersMaps.forEach(m => { let tool = m .getInteractions() .getArray() .find(i => i.get("id") === "cuttool"); if (tool) { tool.setActive(enabled); } }); }, isolinesLegendImgDataURL: (state, isolinesLegendImgDataURL) => { state.isolinesLegendImgDataURL = isolinesLegendImgDataURL; }, differencesLegendImgDataURL: (state, differencesLegendImgDataURL) => { state.differencesLegendImgDataURL = differencesLegendImgDataURL; } }, actions: { openLayersMap({ state, commit, dispatch }, map) { const drawVectorSrc = map.getLayer("DRAWTOOL").getSource(); const cutVectorSrc = map.getLayer("CUTTOOL").getSource(); // init line tool const lineTool = new Draw({ source: drawVectorSrc, type: "LineString", maxPoints: 2 }); lineTool.set("id", "linetool"); lineTool.setActive(false); lineTool.on("drawstart", () => { state.openLayersMaps.forEach(m => { m.getLayer("DRAWTOOL") .getSource() .clear(); }); commit("setCurrentMeasurement", null); }); lineTool.on("drawend", event => { commit("setCurrentMeasurement", { quantity: app.$gettext("Length"), unitSymbol: "m", value: Math.round(getLength(event.feature.getGeometry()) * 10) / 10 }); commit("application/showIdentify", true, { root: true }); }); // init polygon tool const polygonTool = new Draw({ source: drawVectorSrc, type: "Polygon", maxPoints: 50 }); polygonTool.set("id", "polygontool"); polygonTool.setActive(false); polygonTool.on("drawstart", () => { state.openLayersMaps.forEach(m => { m.getLayer("DRAWTOOL") .getSource() .clear(); }); commit("setCurrentMeasurement", null); }); polygonTool.on("drawend", event => { const areaSize = getArea(event.feature.getGeometry()); commit("setCurrentMeasurement", { quantity: app.$gettext("Area"), unitSymbol: areaSize > 100000 ? "km²" : "m²", value: areaSize > 100000 ? Math.round(areaSize / 1000) / 1000 // convert into 1 km² == 1000*1000 m² and round to 1000 m² : Math.round(areaSize) }); commit("application/showIdentify", true, { root: true }); }); // init cut tool const cutTool = new Draw({ source: cutVectorSrc, type: "LineString", maxPoints: 2, style: new Style({ stroke: new Stroke({ color: "#444", width: 2, lineDash: [7, 7] }), image: new Circle({ fill: new Fill({ color: "#333" }), stroke: new Stroke({ color: "#fff", width: 1.5 }), radius: 6 }) }) }); cutTool.set("id", "cuttool"); cutTool.setActive(false); cutTool.on("drawstart", () => { state.openLayersMaps.forEach(m => { m.getLayer("CUTTOOL") .getSource() .clear(); }); }); cutTool.on("drawend", event => { commit("fairwayprofile/selectedCut", null, { root: true }); dispatch("fairwayprofile/cut", event.feature, { root: true }); }); map.addInteraction(lineTool); map.addInteraction(cutTool); map.addInteraction(polygonTool); // If there are multiple maps and you enable one of the draw tools, when // moving the mouse to another map, the cursor for the draw tool stays // visible in the first map, right next to the edge where the cursor left // the map. So here we disable all draw layers except the ones in the map // that the user currently hovering with the mouse. map.getTargetElement().addEventListener("mouseenter", () => { if ( state.lineToolEnabled || state.polygonToolEnabled || state.cutToolEnabled ) { state.openLayersMaps.forEach(m => { let lineTool = m .getInteractions() .getArray() .find(i => i.get("id") === "linetool"); let polygonTool = m .getInteractions() .getArray() .find(i => i.get("id") === "polygontool"); let cutTool = m .getInteractions() .getArray() .find(i => i.get("id") === "cuttool"); if (lineTool) lineTool.setActive(false); if (polygonTool) polygonTool.setActive(false); if (cutTool) cutTool.setActive(false); }); let lineTool = map .getInteractions() .getArray() .find(i => i.get("id") === "linetool"); let polygonTool = map .getInteractions() .getArray() .find(i => i.get("id") === "polygontool"); let cutTool = map .getInteractions() .getArray() .find(i => i.get("id") === "cuttool"); if (lineTool && state.lineToolEnabled) lineTool.setActive(true); if (polygonTool && state.polygonToolEnabled) polygonTool.setActive(true); if (cutTool && state.cutToolEnabled) cutTool.setActive(true); } }); commit("addOpenLayersMap", map); }, initIdentifyTool({ state, rootState, commit, dispatch }, map) { map.on(["singleclick", "dblclick"], event => { if ( state.lineToolEnabled || state.polygonToolEnabled || state.cutToolEnabled ) return; commit("setIdentifiedFeatures", []); // checking our WFS layers var features = map.getFeaturesAtPixel(event.pixel, { hitTolerance: 7 }); if (features) { let identifiedFeatures = []; for (let feature of features) { let id = feature.getId(); // avoid identifying the same feature twice if ( identifiedFeatures.findIndex( f => f.getId() === feature.getId() ) === -1 ) { identifiedFeatures.push(feature); } // get selected bottleneck // RegExp.prototype.test() works with number, str and undefined if (/^bottlenecks/.test(id)) { if ( rootState.bottlenecks.selectedBottleneck != feature.get("objnam") ) { dispatch( "bottlenecks/setSelectedBottleneck", feature.get("objnam"), { root: true } ).then(() => { this.commit("bottlenecks/setFirstSurveySelected"); }); dispatch("moveMap", { coordinates: getCenter( feature .getGeometry() .clone() .transform("EPSG:3857", "EPSG:4326") .getExtent() ), zoom: 17, preventZoomOut: true }); } } // get selected gauge if (/^gauges/.test(id)) { if ( rootState.gauges.selectedGaugeISRS !== feature.get("isrs_code") ) { dispatch("gauges/selectedGaugeISRS", feature.get("isrs_code"), { root: true }); dispatch("moveMap", { coordinates: getCenter( feature .getGeometry() .clone() .transform("EPSG:3857", "EPSG:4326") .getExtent() ), zoom: 15, preventZoomOut: true }); } } // get selected stretch if (/^stretches/.test(id)) { if (rootState.imports.selectedStretchId === feature.getId()) { commit("imports/selectedStretchId", null, { root: true }); } else { commit("imports/selectedStretchId", feature.getId(), { root: true }); dispatch("moveMap", { coordinates: getCenter( feature .getGeometry() .clone() .transform("EPSG:3857", "EPSG:4326") .getExtent() ), zoom: null, preventZoomOut: true }); } } } commit("setIdentifiedFeatures", identifiedFeatures); } // DEBUG output and example how to remove the GeometryName /* for (let feature of features) { console.log("Identified:", feature.getId()); for (let key of feature.getKeys()) { if (key != feature.getGeometryName()) { console.log(key, feature.get(key)); } } } */ var waterwayAxisSource = map.getLayer("WATERWAYAXIS").getSource(); var waxisUrl = waterwayAxisSource.getGetFeatureInfoUrl( event.coordinate, 100 /* resolution */, "EPSG:3857", // { INFO_FORMAT: "application/vnd.ogc.gml" } // not allowed by d4d { INFO_FORMAT: "application/json" } ); if (waxisUrl) { // cannot directly query here because of SOP HTTP.get(waxisUrl, { headers: { "X-Gemma-Auth": localStorage.getItem("token") } }).then(response => { let features = response.data.features.map(f => { let feat = new Feature({ geometry: new Point(f.geometry.coordinates) }); feat.setId(f.id); feat.setProperties(f.properties); return feat; }); commit("addIdentifiedFeatures", features); }); } var waterwayAreaSource = map.getLayer("WATERWAYAREA").getSource(); var wareaUrl = waterwayAreaSource.getGetFeatureInfoUrl( event.coordinate, 100 /* resolution */, "EPSG:3857", // { INFO_FORMAT: "application/vnd.ogc.gml" } // not allowed by d4d { INFO_FORMAT: "application/json" } ); if (wareaUrl) { HTTP.get(wareaUrl, { headers: { "X-Gemma-Auth": localStorage.getItem("token") } }).then(response => { let features = response.data.features.map(f => { let feat = new Feature({ geometry: new Point(f.geometry.coordinates) }); feat.setId(f.id); feat.setProperties(f.properties); return feat; }); commit("addIdentifiedFeatures", features); }); } var dmSource = map.getLayer("DISTANCEMARKS").getSource(); var dmUrl = dmSource.getGetFeatureInfoUrl( event.coordinate, 100 /* resolution */, "EPSG:3857", // { INFO_FORMAT: "application/vnd.ogc.gml" } // not allowed by d4d { INFO_FORMAT: "application/json" } ); if (dmUrl) { HTTP.get(dmUrl + "&BUFFER=5", { headers: { "X-Gemma-Auth": localStorage.getItem("token") } }).then(response => { let features = response.data.features.map(f => { let feat = new Feature({ geometry: new Point(f.geometry.coordinates) }); feat.setId(f.id); feat.setProperties(f.properties); return feat; }); commit("addIdentifiedFeatures", features); }); } var dmaSource = map.getLayer("DISTANCEMARKSAXIS").getSource(); var dmaUrl = dmaSource.getGetFeatureInfoUrl( event.coordinate, 100 /* resolution */, "EPSG:3857", // { INFO_FORMAT: "application/vnd.ogc.gml" } // not allowed by d4d { INFO_FORMAT: "application/json" } ); if (dmaUrl) { HTTP.get(dmaUrl + "&BUFFER=5", { headers: { "X-Gemma-Auth": localStorage.getItem("token") } }).then(response => { let features = response.data.features.map(f => { let feat = new Feature({ geometry: new Point(f.geometry.coordinates) }); feat.setId(f.id); feat.setProperties(f.properties); return feat; }); commit("addIdentifiedFeatures", features); }); } // trying the GetFeatureInfo way for WMS var iecdisSource = map.getLayer("INLANDECDIS").getSource(); var iecdisUrl = iecdisSource.getGetFeatureInfoUrl( event.coordinate, 100 /* resolution */, "EPSG:3857", // { INFO_FORMAT: "application/vnd.ogc.gml" } // not allowed by d4d { INFO_FORMAT: "text/plain" } ); if (iecdisUrl) { // cannot directly query here because of SOP console.log("GetFeatureInfo url:", iecdisUrl); } }); }, moveToBoundingBox({ state }, { boundingBox, zoom, preventZoomOut }) { const extent = transformExtent(boundingBox, "EPSG:4326", "EPSG:3857"); const currentZoom = state.syncedView.getZoom(); zoom = zoom || currentZoom; state.syncedView.fit(extent, { maxZoom: preventZoomOut ? Math.max(zoom, currentZoom) : zoom, duration: 700 }); }, moveToFeauture({ dispatch }, { feature, zoom, preventZoomOut }) { const boundingBox = bbox(feature.geometry); dispatch("moveToBoundingBox", { boundingBox, zoom, preventZoomOut }); }, moveMap({ state }, { coordinates, zoom, preventZoomOut }) { const currentZoom = state.syncedView.getZoom(); zoom = zoom || currentZoom; state.syncedView.animate({ zoom: preventZoomOut ? Math.max(zoom, currentZoom) : zoom, center: fromLonLat(coordinates, state.syncedView.getProjection()), duration: 700 }); } } };