Mercurial > gemma
view client/src/components/map/Map.vue @ 4837:3b0ec9b56d7c
Merged
author | Sascha Wilde <wilde@intevation.de> |
---|---|
date | Fri, 08 Nov 2019 13:10:56 +0100 |
parents | a905438a7935 |
children | 008bc1ae8897 |
line wrap: on
line source
<template> <div :id="'map-' + paneId" :class="['map', { nocursor: this.hasActiveInteractions }]" > <Zoom :map="map" /> </div> </template> <style lang="sass" scoped> .map width: 100% height: 100% background-color: #eee background-image: linear-gradient(45deg, #e8e8e8 25%, transparent 25%, transparent 75%, #e8e8e8 75%, #e8e8e8), linear-gradient(45deg, #e8e8e8 25%, transparent 25%, transparent 75%, #e8e8e8 75%, #e8e8e8) background-size: 20px 20px background-position: 0 0, 10px 10px &.nocursor cursor: none </style> <script> /* 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): * * Thomas Junk <thomas.junk@intevation.de> * * Bernhard E. Reiter <bernhard.reiter@intevation.de> */ import { HTTP } from "@/lib/http"; import { mapState } from "vuex"; import { Map, View } from "ol"; import { Stroke, Style, Fill } from "ol/style"; import { displayError } from "@/lib/errors"; import { pane } from "@/lib/mixins"; import { layerFactory } from "@/components/map/layers"; import { ImageWMS as ImageSource } from "ol/source"; import { styles } from "./styles"; import "ol/ol.css"; /* for the sake of debugging */ /* eslint-disable no-console */ export default { mixins: [pane], components: { Zoom: () => import("@/components/map/Zoom") }, data() { return { map: null }; }, computed: { ...mapState("map", [ "initialLoad", "extent", "syncedMaps", "syncedView", "ongoingRefresh" ]), ...mapState("bottlenecks", ["selectedSurvey"]), ...mapState("fairwayprofile", ["additionalSurvey"]), ...mapState("application", ["paneSetup", "paneRotate", "config"]), ...mapState("imports", ["selectedStretchId", "selectedSectionId"]), layers() { return layerFactory(this.paneId); }, hasActiveInteractions() { return ( this.map && this.map .getInteractions() .getArray() .filter( i => ["linetool", "polygontool", "cuttool"].includes(i.get("id")) && i.getActive() ).length ); } }, watch: { ongoingRefresh() { if (this.ongoingRefresh) return; this.loadStyles(); }, paneSetup() { this.$nextTick(() => this.map.updateSize()); }, paneRotate() { this.$nextTick(() => this.map.updateSize()); }, syncedMaps(syncedMaps) { if (syncedMaps.includes(this.paneId) || this.paneId === "main") { this.map.setView(this.syncedView); } else { this.map.setView( new View({ enableRotation: false, center: [this.extent.lon, this.extent.lat], minZoom: 5, // restrict zooming out to ~size of Europe for width 1000px zoom: this.extent.zoom, projection: "EPSG:3857" }) ); } }, selectedSurvey(survey) { if (this.paneId === "main") { if (survey) { this.updateBottleneckFilter(survey.bottleneck_id, survey.date_info); } else { this.updateBottleneckFilter("does_not_exist", "1999-10-01"); } } }, additionalSurvey(survey) { if (this.paneId === "compare-survey") { if (survey) { this.updateBottleneckFilter(survey.bottleneck_id, survey.date_info); } else { this.updateBottleneckFilter("does_not_exist", "1999-10-01"); } } }, selectedStretchId(id) { let stretch = this.layers.get("STRETCHES"); stretch .getSource() .getFeatures() .forEach(f => { f.set("highlighted", false); f.setStyle(null); if (id === f.getId()) { f.set("highlighted", true); let highlight = new Style({ fill: new Fill({ color: this.colorLuminance( stretch .getStyle() .getFill() .getColor(), 0.3 ) }), stroke: new Stroke({ color: this.colorLuminance( stretch .getStyle() .getStroke() .getColor(), 0.3 ), width: 3 }) }); f.setStyle(highlight); } }); }, selectedSectionId(id) { let section = this.layers.get("SECTIONS"); section .getSource() .getFeatures() .forEach(f => { f.set("highlighted", false); if (id === f.getId()) { f.set("highlighted", true); let highlight = new Style({ fill: new Fill({ color: this.colorLuminance( section .getStyle() .getFill() .getColor(), 0.3 ) }), stroke: new Stroke({ color: this.colorLuminance( section .getStyle() .getStroke() .getColor(), 0.3 ), width: 4 }) }); f.setStyle(highlight); } }); } }, methods: { colorLuminance(color, lum) { let [r, g, b, a] = color .substring(5, color.length - 1) .split(",") .map(e => Number(e)); let [r1, g1, b1] = [r, g, b].map(e => Math.round(Math.min(Math.max(0, e + e * lum), 255)) ); return `rgba(${r1},${g1},${b1},${a})`; }, updateBottleneckFilter(bottleneck_id, datestr) { if (!bottleneck_id) return; const exists = bottleneck_id != "does_not_exist"; if (exists) { this.layers .get("BOTTLENECKISOLINE") .getSource() .updateParams({ cql_filter: `date_info='${datestr}' AND bottleneck_id='${bottleneck_id}'` }); } this.layers.get("BOTTLENECKISOLINE").setVisible(exists); }, initMap() { if (!this.syncedView) { this.$store.commit( "map/syncedView", new View({ enableRotation: false, center: [this.extent.lon, this.extent.lat], minZoom: 5, // restrict zooming out to ~size of Europe for width 1000px zoom: this.extent.zoom, projection: "EPSG:3857" }) ); } // move to user specific default extent if map loads for the first time // checking initialLoad will be obsolete once we abandoned the separated admin context if (this.initialLoad) { this.$store.commit("map/initialLoad", false); var currentUser = this.$store.state.user.user; HTTP.get("/users/" + encodeURIComponent(`${currentUser}`), { headers: { "X-Gemma-Auth": localStorage.getItem("token"), "Content-type": "text/xml; charset=UTF-8" } }) .then(response => { this.mountMap(); this.$store.dispatch("map/moveToBoundingBox", { boundingBox: [ response.data.extent.x1, response.data.extent.y1, response.data.extent.x2, response.data.extent.y2 ], zoom: 17, preventZoomOut: true, duration: 0 }); }) .catch(error => { this.mountMap(); const { status, data } = error.response; displayError({ title: this.$gettext("Backend Error"), message: `${status}: ${data.message || data}` }); }); } else { this.mountMap(); } }, mountMap() { const source = new ImageSource({ preload: 1, url: this.config.ecdis_wms_url, crossOrigin: "anonymous", params: JSON.parse(this.config.ecdis_wms_params) }); this.layers.get("INLANDECDIS").setSource(source); this.map = new Map({ layers: this.layers.config, target: "map-" + this.paneId, controls: [], view: this.syncedMaps.includes(this.paneId) || this.paneId === "main" ? this.syncedView : new View({ center: [this.extent.lon, this.extent.lat], minZoom: 5, zoom: this.extent.zoom, projection: "EPSG:3857" }) }); this.map.getLayer = id => this.layers.get(id); // store map position on every move // will be obsolete once we abandoned the separated admin context this.map.on("moveend", event => { const center = event.map.getView().getCenter(); this.$store.commit("map/extent", { lat: center[1], lon: center[0], zoom: event.map.getView().getZoom() }); }); this.$store.dispatch("map/openLayersMap", this.map); this.$store.dispatch("map/initIdentifyTool", this.map); }, loadStyles() { const getRGBA = color => { return ( "rgba(" + parseInt(color.slice(1, 3), 16) + ", " + parseInt(color.slice(3, 5), 16) + ", " + parseInt(color.slice(5, 7), 16) + ", " + (color.length > 7 ? parseInt(color.slice(7, 9), 16) / 255 : "1") + ")" ); }; // load configured bottleneck colors HTTP.get("/system/settings", { headers: { "X-Gemma-Auth": localStorage.getItem("token") } }).then(response => { let btlnStrokeC = getRGBA(response.data.bottlenecks_stroke), btlnFillC = getRGBA(response.data.bottlenecks_fill), strFillC = getRGBA(response.data.stretches_fill), strStrokeC = getRGBA(response.data.stretches_stroke), secStrokeC = getRGBA(response.data.sections_stroke), secFillC = getRGBA(response.data.sections_fill), fwd1StrokeC = getRGBA(response.data.fairwaydimensionslos1_stroke), fwd1FillC = getRGBA(response.data.fairwaydimensionslos1_fill), fwd2StrokeC = getRGBA(response.data.fairwaydimensionslos2_stroke), fwd2FillC = getRGBA(response.data.fairwaydimensionslos2_fill), fwd3StrokeC = getRGBA(response.data.fairwaydimensionslos3_stroke), fwd3FillC = getRGBA(response.data.fairwaydimensionslos3_fill), wwpStokeC = getRGBA(response.data.waterwayprofiles_stroke); let btlnStyle = new Style({ stroke: new Stroke({ color: btlnStrokeC, width: 4 }), fill: new Fill({ color: btlnFillC }) }), strStyle = new Style({ stroke: new Stroke({ color: strStrokeC, width: 2 }), fill: new Fill({ color: strFillC }) }), secStyle = new Style({ stroke: new Stroke({ color: secStrokeC, width: 5 }), fill: new Fill({ color: secFillC }) }), fwd1Style = new Style({ stroke: new Stroke({ lineDash: [2, 4], lineCap: "round", color: fwd1StrokeC, width: 2 }), fill: new Fill({ color: fwd1FillC }) }), fwd2Style = new Style({ stroke: new Stroke({ lineDash: [3, 6], lineCap: "round", color: fwd2StrokeC, width: 2 }), fill: new Fill({ color: fwd2FillC }) }), fwd3Style = new Style({ stroke: new Stroke({ color: fwd3StrokeC, width: 2 }), fill: new Fill({ color: fwd3FillC }) }), wwpStyle = new Style({ stroke: new Stroke({ color: wwpStokeC, lineDash: [5, 5], width: 2 }) }); this.layers.get("WATERWAYPROFILES").setStyle(wwpStyle); this.layers .get("FAIRWAYDIMENSIONSLOS1") .setStyle(() => [fwd1Style, styles.textFW1]); this.layers .get("FAIRWAYDIMENSIONSLOS2") .setStyle(() => [fwd2Style, styles.textFW2]); this.layers .get("FAIRWAYDIMENSIONSLOS3") .setStyle(() => [fwd3Style, styles.textFW3]); this.layers.get("SECTIONS").setStyle(secStyle); this.layers.get("STRETCHES").setStyle(strStyle); this.layers.get("BOTTLENECKS").setStyle(btlnStyle); this.$store.commit("gauges/deleteNashSutcliffeCache"); this.$store.dispatch("map/refreshLayers"); }); } }, mounted() { // ToDo set path to correct endpoint in order to retrieve an OSM URL HTTP.get("/system/config", { headers: { "X-Gemma-Auth": localStorage.getItem("token") } }) .then(response => { if (response.data["osm-url"]) { this.layers .get("OPENSTREETMAP") .getSource() .setUrl(response.data["osm-url"]); } this.initMap(); if (this.selectedSurvey && this.paneId === "main") { this.updateBottleneckFilter( this.selectedSurvey.bottleneck_id, this.selectedSurvey.date_info ); } if (this.additionalSurvey && this.paneId === "compare-survey") { this.updateBottleneckFilter( this.additionalSurvey.bottleneck_id, this.additionalSurvey.date_info ); } this.loadStyles(); }) .catch(error => { const { status, data } = error.response; displayError({ title: "Backend Error", message: `${status}: ${data.message || data}` }); }); }, destroyed() { this.$store.commit("map/removeOpenLayersMap", this.map); } }; </script>