Mercurial > gemma
changeset 649:83081ba6c9c1
feat: Linetool added
In order to draw lines for allocating profiles,
a basic implementation of line drawing was added.
author | Thomas Junk <thomas.junk@intevation.de> |
---|---|
date | Thu, 13 Sep 2018 16:55:53 +0200 |
parents | 620a65f11b33 |
children | 2745ac1ebe1e |
files | client/src/App.vue client/src/application/Linetool.vue client/src/application/Main.vue client/src/application/Topbar.vue client/src/application/stores/application.js client/src/map/Maplayer.vue |
diffstat | 6 files changed, 133 insertions(+), 48 deletions(-) [+] |
line wrap: on
line diff
--- a/client/src/App.vue Thu Sep 13 14:11:33 2018 +0200 +++ b/client/src/App.vue Thu Sep 13 16:55:53 2018 +0200 @@ -1,12 +1,12 @@ <template> <div id="app" class="main"> - <div class="d-flex flex-column userinterface"> + <div v-if="isAuthenticated" class="d-flex flex-column userinterface"> <div class="topcontainer"> - <Topbar v-if="isAuthenticated"></Topbar> + <Topbar :routeName="routeName"></Topbar> </div> <div class="midcontainer d-flex flex-row"> <div class="leftcontainer"> - <Sidebar v-if="isAuthenticated"></Sidebar> + <Sidebar></Sidebar> </div> <div class="middle"> @@ -16,7 +16,8 @@ </div> </div> <div class="bottomcontainer d-flex flex-row align-items-end"> - <Userbar v-if="isAuthenticated"></Userbar> + <Userbar></Userbar> + <Linetool v-if="routeName != 'usermanagement'"></Linetool> </div> </div> <div class="d-flex flex-column"> @@ -87,16 +88,22 @@ import Topbar from "./application/Topbar"; import { mapGetters } from "vuex"; import Userbar from "./application/Userbar"; +import Linetool from "./application/Linetool"; export default { name: "app", computed: { - ...mapGetters("user", ["isAuthenticated"]) + ...mapGetters("user", ["isAuthenticated"]), + routeName() { + const routeName = this.$route.name; + return routeName; + } }, components: { Sidebar, Topbar, - Userbar + Userbar, + Linetool } }; </script>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/application/Linetool.vue Thu Sep 13 16:55:53 2018 +0200 @@ -0,0 +1,45 @@ +<template> + <div @click="drawLine" class="ui-element d-flex shadow drawtool"> + <i :class="icon"></i> + </div> +</template> + +<style lang="scss"> +.drawtool { + position: absolute; + bottom: 0; + right: 0; + background-color: white; + padding: $small-offset; + border-radius: $border-radius; + margin-left: $offset; + height: $icon-width; + width: $icon-height; + margin-bottom: $offset; + margin-right: $offset; + z-index: 2; +} +</style> + +<script> +import { mapGetters } from "vuex"; + +export default { + name: "linetool", + methods: { + drawLine() { + this.$store.commit("application/toggleDrawModeLine"); + } + }, + computed: { + ...mapGetters("application", ["drawMode"]), + icon() { + return { + fa: true, + "fa-pencil": !this.drawMode, + "fa-pencil-square": this.drawMode + }; + } + } +}; +</script>
--- a/client/src/application/Main.vue Thu Sep 13 14:11:33 2018 +0200 +++ b/client/src/application/Main.vue Thu Sep 13 16:55:53 2018 +0200 @@ -1,6 +1,6 @@ <template> <div class="main d-flex flex-column"> - <Maplayer :split="isSplitscreen" :lat="6155376" :long="1819178" :zoom="11"></Maplayer> + <Maplayer :drawMode="drawMode" :split="isSplitscreen" :lat="6155376" :long="1819178" :zoom="11"></Maplayer> <div v-if="isSplitscreen" class="profile d-flex flex-row"> <FairwayProfile :data="currentProfile" :height="height" :width="width" :xScale="xAxis" :yScaleLeft="yAxisLeft" :yScaleRight="yAxisRight" :margin="margins"></FairwayProfile> </div> @@ -51,7 +51,7 @@ }; }, computed: { - ...mapGetters("application", ["isSplitscreen"]), + ...mapGetters("application", ["isSplitscreen", "drawMode"]), ...mapGetters("fairwayprofile", ["currentProfile"]), xAxis() { return [this.xScale.x, this.xScale.y]; @@ -70,6 +70,7 @@ window.addEventListener("resize", debounce(this.scaleFairwayProfile), 100); }, updated() { + if (!document.querySelector(".profile")) return; this.height = document.querySelector(".profile").clientHeight - 25; this.width = document.querySelector(".profile").clientWidth - 100; },
--- a/client/src/application/Topbar.vue Thu Sep 13 14:11:33 2018 +0200 +++ b/client/src/application/Topbar.vue Thu Sep 13 16:55:53 2018 +0200 @@ -71,6 +71,7 @@ components: { Layers: Layers }, + props: ["routeName"], methods: { toggleSidebar() { this.$store.commit("application/toggleSidebar"); @@ -78,12 +79,6 @@ splitScreen() { this.$store.commit("application/toggleSplitScreen"); } - }, - computed: { - routeName() { - const routeName = this.$route.name; - return routeName; - } } }; </script>
--- a/client/src/application/stores/application.js Thu Sep 13 14:11:33 2018 +0200 +++ b/client/src/application/stores/application.js Thu Sep 13 16:55:53 2018 +0200 @@ -7,6 +7,10 @@ }; }; +const DRAWMODES = { + LINE: "LineString" +}; + const Application = { namespaced: true, state: { @@ -19,7 +23,8 @@ usermenu: { iscollapsed: defaultCollapseState }, - countries: ["AT", "SK", "HU", "HR", "RS", "BiH", "BG", "RO", "UA"] + countries: ["AT", "SK", "HU", "HR", "RS", "BiH", "BG", "RO", "UA"], + drawMode: null }, getters: { countries: state => { @@ -42,6 +47,9 @@ }, splitMode: state => { return state.splitsceen.mode; + }, + drawMode: state => { + return state.drawMode; } }, mutations: { @@ -68,6 +76,13 @@ }, resetSplitScreen: state => { state.splitsceen = initializeSplitScreen(); + }, + toggleDrawModeLine: state => { + if (state.drawMode && state.drawMode === DRAWMODES.LINE) { + state.drawMode = null; + return; + } + state.drawMode = DRAWMODES.LINE; } }, actions: {}
--- a/client/src/map/Maplayer.vue Thu Sep 13 14:11:33 2018 +0200 +++ b/client/src/map/Maplayer.vue Thu Sep 13 16:55:53 2018 +0200 @@ -10,24 +10,6 @@ .mapfull { height: 100vh; } - -.ol-zoom { - display: flex; - left: 16vw; - z-index: 5; - top: 1rem; - padding: 0.3rem; - background-color: white; - box-shadow: $basic-shadow; -} - -.ol-attribution { - padding: 0.3rem; - background-color: white; - box-shadow: $basic-shadow; - margin-bottom: 1rem; - margin-right: 0.3rem; -} </style> <script> @@ -38,14 +20,20 @@ // import { greaterThan as greaterThanFilter } from "ol/format/filter.js"; import { WFS, GeoJSON } from "ol/format.js"; import { mapGetters } from "vuex"; +import Draw from "ol/interaction/Draw.js"; +import { Vector as VectorSource } from "ol/source.js"; +import { Vector as VectorLayer } from "ol/layer.js"; export default { name: "maplayer", - props: ["lat", "long", "zoom", "split"], + props: ["drawMode", "lat", "long", "zoom", "split"], data() { return { projection: "EPSG:3857", - openLayersMap: null + openLayersMap: null, + interaction: null, + vectorLayer: null, + vectorSource: null }; }, computed: { @@ -57,13 +45,45 @@ }; }, layerData() { - return this.layers.map(x => { + const l = this.layers.map(x => { return x.data; }); + return [...l, this.vectorLayer]; } }, - methods: {}, + methods: { + createVectorSource() { + this.vectorSource = new VectorSource({ wrapX: false }); + }, + createVectorLayer() { + this.vectorLayer = new VectorLayer({ + source: this.vectorSource + }); + }, + removeCurrentInteraction() { + this.openLayersMap.removeInteraction(this.interaction); + this.interaction = null; + }, + createInteraction() { + return new Draw({ + source: this.vectorSource, + type: this.drawMode + }); + }, + activateInteraction() { + const interaction = this.createInteraction(this.drawMode); + this.interaction = interaction; + this.openLayersMap.addInteraction(interaction); + } + }, watch: { + drawMode() { + if (this.interaction) { + this.removeCurrentInteraction(); + } else { + this.activateInteraction(); + } + }, split() { const map = this.openLayersMap; this.$nextTick(() => { @@ -72,10 +92,12 @@ } }, mounted() { - var that = this; + this.createVectorSource(); + this.createVectorLayer(); this.openLayersMap = new Map({ layers: this.layerData, target: "map", + controls: [], view: new View({ center: [this.long, this.lat], zoom: this.zoom, @@ -103,12 +125,12 @@ "Content-type": "text/xml; charset=UTF-8" } } - ).then(function(response) { + ).then(response => { var features = new GeoJSON().readFeatures(JSON.stringify(response.data)); - var vectorSrc = that.layers[2].data.getSource(); + var vectorSrc = this.layers[2].data.getSource(); vectorSrc.addFeatures(features); // would scale to the extend of all resulting features - // that.openLayersMap.getView().fit(vectorSrc.getExtent()); + // this.openLayersMap.getView().fit(vectorSrc.getExtent()); }); // FIXME hardwired for now @@ -127,9 +149,9 @@ "Content-type": "text/xml; charset=UTF-8" } } - ).then(function(response) { + ).then(response => { var features = new GeoJSON().readFeatures(JSON.stringify(response.data)); - var vectorSrc = that.layers[3].data.getSource(); + var vectorSrc = this.layers[3].data.getSource(); vectorSrc.addFeatures(features); }); @@ -149,9 +171,9 @@ "Content-type": "text/xml; charset=UTF-8" } } - ).then(function(response) { + ).then(response => { var features = new GeoJSON().readFeatures(JSON.stringify(response.data)); - var vectorSrc = that.layers[4].data.getSource(); + var vectorSrc = this.layers[4].data.getSource(); vectorSrc.addFeatures(features); }); @@ -171,10 +193,10 @@ "Content-type": "text/xml; charset=UTF-8" } } - ).then(function(response) { + ).then(response => { var features = new GeoJSON().readFeatures(JSON.stringify(response.data)); - var vectorSrc = that.layers[5].data.getSource(); - that.layers[5].data.setVisible(that.layers[5].isVisible); + var vectorSrc = this.layers[5].data.getSource(); + this.layers[5].data.setVisible(this.layers[5].isVisible); vectorSrc.addFeatures(features); }); }