view client/src/fairway/Fairwayprofile.vue @ 1030:bf10a7f990cc

refac: fairway profile retrieves current data from store
author Thomas Junk <thomas.junk@intevation.de>
date Wed, 24 Oct 2018 15:09:06 +0200
parents 957613a71b35
children e8ebfbc2aa05
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" @change="selectAdditionalSurveyData">
                <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";

const GROUND_COLOR = "#4A2F06";

export default {
  name: "fairwayprofile",
  props: [
    "width",
    "height",
    "xScale",
    "yScaleLeft",
    "yScaleRight",
    "margin",
    "totalLength",
    "waterLevels",
    "fairwayCoordinates",
    "selectedWaterLevel",
    "minAlt",
    "maxAlt",
    "additionalSurveys"
  ],
  computed: {
    ...mapState("fairwayprofile", [
      "startPoint",
      "endPoint",
      "currentProfile",
      "selectedMorph"
    ]),
    currentData() {
      const currentSurveyDate = this.selectedMorph.date_info;
      return this.currentProfile[currentSurveyDate];
    },
    waterColor() {
      const result = this.waterLevels.find(
        x => x.level === this.selectedWaterLevel
      );
      return result.color;
    }
  },
  data() {
    return {
      additionalSurvey: ""
    };
  },
  watch: {
    currentProfile() {
      this.drawDiagram();
    },
    width() {
      this.drawDiagram();
    },
    height() {
      this.drawDiagram();
    },
    waterLevels() {
      this.drawDiagram();
    },
    selectedWaterLevel() {
      this.drawDiagram();
    },
    fairwayCoordinates() {
      this.drawDiagram();
    }
  },
  methods: {
    selectAdditionalSurveyData() {
      //
    },
    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 {
        xScale,
        yScaleRight,
        yScaleLeft,
        graph
      } = this.generateCoordinates(svg, height, width);
      this.drawWaterlevel({
        graph,
        xScale,
        yScaleRight,
        height,
        width
      });
      this.drawProfile({
        graph,
        xScale,
        yScaleRight,
        currentData,
        height,
        width
      });
      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 }) {
      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", GROUND_COLOR)
          .attr("stroke", GROUND_COLOR)
          .attr("stroke-width", 3)
          .attr("d", profileArea);
        graph
          .append("path")
          .datum(part)
          .attr("fill", "none")
          .attr("stroke", "black")
          .attr("stroke-linejoin", "round")
          .attr("stroke-linecap", "round")
          .attr("stroke-width", 3)
          .attr("d", profileLine);
      }
    }
  },
  mounted() {
    this.drawDiagram();
  }
};
</script>