Mercurial > gemma
view client/src/store/map.js @ 1313:e4e35fb2d995
save map extent (center/zoom) in store, to not lose it when switching between map and admin area
author | Markus Kottlaender <markus@intevation.de> |
---|---|
date | Fri, 23 Nov 2018 15:18:14 +0100 |
parents | 99c039e86624 |
children | ea3a89a1813a |
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 by via donau * – Österreichische Wasserstraßen-Gesellschaft mbH * Software engineering by Intevation GmbH * * Author(s): * Thomas Junk <thomas.junk@intevation.de> */ //import { HTTP } from "../lib/http"; import TileWMS from "ol/source/TileWMS.js"; import { Tile as TileLayer, Vector as VectorLayer } from "ol/layer.js"; import OSM from "ol/source/OSM"; import Draw from "ol/interaction/Draw.js"; import { Icon, Stroke, Style, Fill, Text, Circle } from "ol/style.js"; import VectorSource from "ol/source/Vector.js"; import Point from "ol/geom/Point.js"; import { bbox as bboxStrategy } from "ol/loadingstrategy"; import { HTTP } from "../lib/http"; import { fromLonLat } from "ol/proj"; import { getLength, getArea } from "ol/sphere.js"; // initial state const init = () => { return { openLayersMap: null, 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 lineTool: null, // open layers interaction object (Draw) polygonTool: null, // open layers interaction object (Draw) cutTool: null, // open layers interaction object (Draw) layers: [ { name: "Open Streetmap", data: new TileLayer({ source: new OSM() }), isVisible: true, showInLegend: true }, { name: "Inland ECDIS chart Danube", data: new TileLayer({ source: new TileWMS({ preload: 1, url: "https://demo.d4d-portal.info/wms", params: { LAYERS: "d4d", VERSION: "1.1.1", TILED: true } }) }), isVisible: true, showInLegend: true }, { name: "Fairway Dimensions", data: new VectorLayer({ source: new VectorSource(), style: function(feature) { return [ new Style({ stroke: new Stroke({ color: "rgba(0, 0, 255, 1.0)", width: 2 }) }), new Style({ text: new Text({ font: 'bold 12px "Open Sans", "sans-serif"', placement: "line", fill: new Fill({ color: "black" }), text: "LOS: " + feature.get("level_of_service").toString() //, zIndex: 10 }) }) ]; } }), isVisible: true, showInLegend: true }, { name: "Waterway Area, named", data: new VectorLayer({ source: new VectorSource({ strategy: bboxStrategy }), style: new Style({ stroke: new Stroke({ color: "rgba(0, 132, 0, 1)", width: 2 }) }) }), isVisible: false, showInLegend: true }, { name: "Waterway Area", data: new VectorLayer({ source: new VectorSource({ strategy: bboxStrategy }), style: new Style({ stroke: new Stroke({ color: "rgba(0, 102, 0, 1)", width: 2 }) }) }), isVisible: true, showInLegend: true }, { name: "Waterway Axis", data: new VectorLayer({ source: new VectorSource({ strategy: bboxStrategy }), style: new Style({ stroke: new Stroke({ color: "rgba(0, 0, 255, .5)", lineDash: [5, 5], width: 2 }) }) }), isVisible: true, showInLegend: true }, { name: "Distance marks", forLegendStyle: { point: true, resolution: 8 }, data: new VectorLayer({ source: new VectorSource({ strategy: bboxStrategy }) }), isVisible: false, showInLegend: true }, { name: "Bottlenecks", data: new VectorLayer({ source: new VectorSource({ strategy: bboxStrategy }), style: new Style({ stroke: new Stroke({ color: "rgba(230, 230, 10, .8)", width: 4 }), fill: new Fill({ color: "rgba(230, 230, 10, .3)" }) }) }), isVisible: true, showInLegend: true }, { name: "Bottleneck isolines", data: new TileLayer({ source: new TileWMS({ preload: 0, projection: "EPSG:3857", url: window.location.origin + "/api/internal/wms", params: { LAYERS: "sounding_results_contour_lines_geoserver", VERSION: "1.1.1", TILED: true }, tileLoadFunction: function(tile, src) { // console.log("calling for", tile, src); HTTP.get(src, { headers: { "X-Gemma-Auth": localStorage.getItem("token") }, responseType: "blob" }).then(response => { tile.getImage().src = URL.createObjectURL(response.data); }); } // TODO tile.setState(TileState.ERROR); }) }), isVisible: false, showInLegend: true }, { name: "Distance marks, Axis", forLegendStyle: { point: true, resolution: 8 }, data: new VectorLayer({ source: new VectorSource({ strategy: bboxStrategy }), style: function(feature, resolution) { if (resolution < 10) { var s = new Style({ image: new Circle({ radius: 5, fill: new Fill({ color: "rgba(255, 0, 0, 0.1)" }), stroke: new Stroke({ color: "blue", width: 1 }) }) }); if (resolution < 6) { s.setText( new Text({ offsetY: 12, font: '10px "Open Sans", "sans-serif"', fill: new Fill({ color: "black" }), text: (feature.get("hectometre") / 10).toString() }) ); } return s; } else { return []; } } }), isVisible: true, showInLegend: true }, { name: "Draw Tool", data: new VectorLayer({ source: new VectorSource({ wrapX: false }), style: function(feature) { // adapted from OpenLayer's LineString Arrow Example var geometry = feature.getGeometry(); var styles = [ // linestring new Style({ stroke: new Stroke({ color: "#369aca", width: 2 }) }) ]; if (geometry.getType() === "LineString") { geometry.forEachSegment(function(start, end) { var dx = end[0] - start[0]; var dy = end[1] - start[1]; var rotation = Math.atan2(dy, dx); // arrows styles.push( new Style({ geometry: new Point(end), image: new Icon({ // we need to make sure the image is loaded by Vue Loader src: require("../assets/linestring_arrow.png"), // fiddling with the anchor's y value does not help to // position the image more centered on the line ending, as the // default line style seems to be slightly uncentered in the // anti-aliasing, but the image is not placed with subpixel // precision anchor: [0.75, 0.5], rotateWithView: true, rotation: -rotation }) }) ); }); } return styles; } }), isVisible: true, showInLegend: false }, { name: "Cut Tool", data: new VectorLayer({ source: new VectorSource({ wrapX: false }), style: function(feature) { // adapted from OpenLayer's LineString Arrow Example var geometry = feature.getGeometry(); var styles = [ // linestring new Style({ stroke: new Stroke({ color: "#333333", width: 2, lineDash: [7, 7] }) }) ]; if (geometry.getType() === "LineString") { geometry.forEachSegment(function(start, end) { var dx = end[0] - start[0]; var dy = end[1] - start[1]; var rotation = Math.atan2(dy, dx); // arrows styles.push( new Style({ geometry: new Point(end), image: new Icon({ // we need to make sure the image is loaded by Vue Loader src: require("../assets/linestring_arrow_grey.png"), // fiddling with the anchor's y value does not help to // position the image more centered on the line ending, as the // default line style seems to be slightly uncentered in the // anti-aliasing, but the image is not placed with subpixel // precision anchor: [0.75, 0.5], rotateWithView: true, rotation: -rotation }) }) ); }); } return styles; } }), isVisible: true, showInLegend: false } ] }; }; export default { init, namespaced: true, state: init(), getters: { layersForLegend: state => { return state.layers.filter(layer => layer.showInLegend); }, getLayerByName: state => name => { return state.layers.find(layer => layer.name === name); }, getVSourceByName: (state, getters) => name => { return getters.getLayerByName(name).data.getSource(); } }, mutations: { extent: (state, extent) => { state.extent = extent; }, toggleVisibility: (state, layer) => { state.layers[layer].isVisible = !state.layers[layer].isVisible; state.layers[layer].data.setVisible(state.layers[layer].isVisible); }, openLayersMap: (state, map) => { state.openLayersMap = map; }, setIdentifiedFeatures: (state, identifiedFeatures) => { state.identifiedFeatures = identifiedFeatures; }, setCurrentMeasurement: (state, measurement) => { state.currentMeasurement = measurement; }, lineTool: (state, lineTool) => { state.lineTool = lineTool; }, polygonTool: (state, polygonTool) => { state.polygonTool = polygonTool; }, cutTool: (state, cutTool) => { state.cutTool = cutTool; }, moveMap: (state, { coordinates, zoom, preventZoomOut }) => { let view = state.openLayersMap.getView(); const currentZoom = view.getZoom(); view.animate({ zoom: preventZoomOut ? Math.max(zoom, currentZoom) : zoom, center: fromLonLat(coordinates, view.getProjection()), duration: 700 }); } }, actions: { openLayersMap({ commit, dispatch, getters }, map) { const drawVectorSrc = getters.getVSourceByName("Draw Tool"); const cutVectorSrc = getters.getVSourceByName("Cut Tool"); // init line tool const lineTool = new Draw({ source: drawVectorSrc, type: "LineString", maxPoints: 2 }); lineTool.setActive(false); lineTool.on("drawstart", () => { drawVectorSrc.clear(); commit("setCurrentMeasurement", null); }); lineTool.on("drawend", event => { commit("setCurrentMeasurement", { quantity: "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.setActive(false); polygonTool.on("drawstart", () => { drawVectorSrc.clear(); commit("setCurrentMeasurement", null); }); polygonTool.on("drawend", event => { const areaSize = getArea(event.feature.getGeometry()); commit("setCurrentMeasurement", { quantity: "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.setActive(false); cutTool.on("drawstart", () => { cutVectorSrc.clear(); }); cutTool.on("drawend", event => { dispatch("fairwayprofile/cut", event.feature, { root: true }); }); map.addInteraction(lineTool); map.addInteraction(cutTool); map.addInteraction(polygonTool); commit("lineTool", lineTool); commit("polygonTool", polygonTool); commit("cutTool", cutTool); commit("openLayersMap", map); } } };