Mercurial > gemma
view client/src/fairway/Fairwayprofile.vue @ 1056:28eb62f7c676 crossprofile
additional survey as dynamic property
author | Thomas Junk <thomas.junk@intevation.de> |
---|---|
date | Thu, 25 Oct 2018 16:19:46 +0200 |
parents | 9bd4f82fcd8d |
children | 51d412a79e4f |
line wrap: on
line source
<template> <div class="profiledisplay d-flex flex-row"> <div class="fairwayprofile"></div> <div class="additionalsurveys d-flex flex-column"> <small class="label">Available Additional Surveys</small> <select v-model="additionalSurvey"> <option value="">None</option> <option v-for="survey in additionalSurveys" :key="survey.date_info" >{{survey.date_info}}</option> </select> <small class="mt-2"> <b>Start:</b> <br> Lat: {{ startPoint[1] }} <br> Lon: {{ startPoint[0] }} <br> <b>End:</b> <br> Lat: {{ endPoint[1] }} <br> Lon: {{ endPoint[0] }} <br> </small> </div> </div> </template> <style scoped lang="scss"> .label { margin-bottom: $small-offset; } .waterlevelselection { margin-top: $large-offset; margin-right: $large-offset; } .additionalsurveys { width: 300px; margin-top: $large-offset; margin-bottom: auto; margin-right: $large-offset; margin-left: auto; } .additionalsurveys input { margin-right: $small-offset; } .profiledisplay { width: 100vw; } .fairwayprofile { background-color: white; margin-left: auto; margin-right: $offset; margin-top: auto; margin-bottom: auto; } </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 by via donau * – Österreichische Wasserstraßen-Gesellschaft mbH * Software engineering by Intevation GmbH * * Author(s): * Thomas Junk <thomas.junk@intevation.de> */ import * as d3 from "d3"; import { mapState } from "vuex"; import { displayError } from "../application/lib/errors.js"; const GROUND_COLOR = "#4A2F06"; export default { name: "fairwayprofile", props: [ "width", "height", "xScale", "yScaleLeft", "yScaleRight", "margin", "additionalSurveys" ], computed: { ...mapState("fairwayprofile", [ "startPoint", "endPoint", "currentProfile", "selectedMorph", "minAlt", "maxAlt", "totalLength", "fairwayCoordinates", "waterLevels", "selectedWaterLevel" ]), additionalSurvey: { get() { return this.$store.getters["fairwayprofile/additionalSurvey"]; }, set(value) { this.$store.commit("fairwayprofile/setAdditionalSurvey", value); this.selectAdditionalSurveyData(); } }, currentData() { const currentSurveyDate = this.selectedMorph.date_info; return this.currentProfile[currentSurveyDate]; }, additionalData() { return this.currentProfile[this.additionalSurvey]; }, waterColor() { const result = this.waterLevels.find( x => x.level === this.selectedWaterLevel ); return result.color; } }, data() { return { wait: false }; }, watch: { currentData() { this.drawDiagram(); }, width() { this.drawDiagram(); }, height() { this.drawDiagram(); }, waterLevels() { this.drawDiagram(); }, selectedWaterLevel() { this.drawDiagram(); }, fairwayCoordinates() { this.drawDiagram(); } }, methods: { selectAdditionalSurveyData() { if ( !this.additionalSurvey || this.wait || this.currentProfile[this.additionalSurvey] ) { this.drawDiagram(); return; } this.$store .dispatch("fairwayprofile/loadProfile", this.additionalSurvey) .then(() => { this.wait = false; }) .catch(error => { this.wait = false; let status = "ERROR"; let data = error; const response = error.response; if (response) { status = response.status; data = response.data; } displayError({ title: "Backend Error", message: `${status}: ${data.message || data}` }); }); }, drawDiagram() { const chartDiv = document.querySelector(".fairwayprofile"); d3.select("svg").remove(); let svg = d3.select(chartDiv).append("svg"); svg.attr("width", this.width); svg.attr("height", this.height); const width = this.width - this.margin.right - 1.5 * this.margin.left; const height = this.height - this.margin.top - 2 * this.margin.bottom; const currentData = this.currentData; const additionalData = this.additionalData; const { xScale, yScaleRight, yScaleLeft, graph } = this.generateCoordinates(svg, height, width); this.drawWaterlevel({ graph, xScale, yScaleRight, height, width }); this.drawProfile({ graph, xScale, yScaleRight, currentData, height, width, color: GROUND_COLOR, strokeColor: "black", opacity: 1 }); if (additionalData) { this.drawProfile({ graph, xScale, yScaleRight, currentData: additionalData, height, width, color: GROUND_COLOR, strokeColor: "#943007", opacity: 0.6 }); } this.drawLabels({ graph, xScale, yScaleLeft, currentData, height, width }); this.drawFairway({ graph, xScale, yScaleRight, currentData, height, width }); }, drawFairway({ graph, xScale, yScaleRight }) { for (let coordinates of this.fairwayCoordinates) { const [startPoint, endPoint, depth] = coordinates; let fairwayArea = d3 .area() .x(function(d) { return xScale(d.x); }) .y0(yScaleRight(0)) .y1(function(d) { return yScaleRight(d.y); }); graph .append("path") .datum([{ x: startPoint, y: -depth }, { x: endPoint, y: -depth }]) .attr("fill", "#002AFF") .attr("stroke-opacity", 0.65) .attr("fill-opacity", 0.65) .attr("stroke", "#FFD20D") .attr("d", fairwayArea); } }, drawLabels({ graph, height }) { graph .append("text") .attr("transform", ["rotate(-90)"]) .attr("y", this.width - 60) .attr("x", -(this.height - this.margin.top - this.margin.bottom) / 2) .attr("dy", "1em") .attr("fill", "black") .style("text-anchor", "middle") .text("Depth [m]"); graph .append("text") .attr("y", 0 - this.margin.left) .attr("x", 0 - height / 4) .attr("dy", "1em") .attr("fill", "black") .style("text-anchor", "middle") .attr("transform", [ "translate(" + this.width / 2 + "," + this.height + ")", "rotate(0)" ]) .text("Width [m]"); }, generateCoordinates(svg, height, width) { let xScale = d3 .scaleLinear() .domain(this.xScale) .rangeRound([0, width]); xScale.ticks(5); let yScaleLeft = d3 .scaleLinear() .domain(this.yScaleLeft) .rangeRound([height, 0]); let yScaleRight = d3 .scaleLinear() .domain(this.yScaleRight) .rangeRound([height, 0]); let xAxis = d3.axisBottom(xScale); let yAxis2 = d3.axisRight(yScaleRight); let graph = svg .append("g") .attr( "transform", "translate(" + this.margin.left + "," + this.margin.top + ")" ); graph .append("g") .attr("transform", "translate(0," + height + ")") .call(xAxis.ticks(5)); graph .append("g") .attr("transform", "translate(" + width + ",0)") .call(yAxis2); return { xScale, yScaleLeft, yScaleRight, graph }; }, drawWaterlevel({ graph, xScale, yScaleRight, height }) { let waterArea = d3 .area() .x(function(d) { return xScale(d.x); }) .y0(height) .y1(function(d) { return yScaleRight(d.y); }); graph .append("path") .datum([{ x: 0, y: 0 }, { x: this.totalLength, y: 0 }]) .attr("fill", this.waterColor) .attr("stroke", this.waterColor) .attr("d", waterArea); }, drawProfile({ graph, xScale, yScaleRight, currentData, height, color, strokeColor, opacity }) { for (let part of currentData) { let profileLine = d3 .line() .x(d => { return xScale(d.x); }) .y(d => { return yScaleRight(-d.y); }); let profileArea = d3 .area() .x(function(d) { return xScale(d.x); }) .y0(height) .y1(function(d) { return yScaleRight(-d.y); }); graph .append("path") .datum(part) .attr("fill", color) .attr("stroke", color) .attr("stroke-width", 3) .attr("stroke-opacity", opacity) .attr("fill-opacity", opacity) .attr("d", profileArea); graph .append("path") .datum(part) .attr("fill", "none") .attr("stroke", strokeColor) .attr("stroke-linejoin", "round") .attr("stroke-linecap", "round") .attr("stroke-width", 3) .attr("stroke-opacity", opacity) .attr("fill-opacity", opacity) .attr("d", profileLine); } } }, mounted() { this.drawDiagram(); } }; </script>