Mercurial > gemma
view client/src/components/fairway/AvailableFairwayDepth.vue @ 3213:b3a1ecdda797
available_fairway_depth: hours in days
author | Thomas Junk <thomas.junk@intevation.de> |
---|---|
date | Thu, 09 May 2019 10:52:54 +0200 |
parents | 66e90b48387a |
children | ee6a4e8af766 |
line wrap: on
line source
<template> <div class="d-flex flex-column flex-fill"> <UIBoxHeader icon="chart-area" :title="title" :closeCallback="close" /> <UISpinnerOverlay v-if="loading" /> <div class="mt-3 d-flex flex-row my-auto"> <div :id="containerId" class="ml-auto diagram-container"></div> </div> </div> </template> <style></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> * Markus Kottländer <markus.kottlaender@intevation.de> */ import * as d3 from "d3"; import app from "@/main"; import debounce from "debounce"; import { diagram } from "@/lib/mixins"; import { mapState } from "vuex"; import filters from "@/lib/filters.js"; const hoursInDays = x => x / 24; export default { mixins: [diagram], data() { return { containerId: "availablefairwaydepth", loading: false, width: 1000, height: 600, paddingRight: 100, spaceBetween: 80, labelPaddingTop: 15, scalePaddingLeft: 50, paddingTop: 10, legend: "", diagram: null, yScale: null, barsWidth: 60, dimensions: null }; }, created() { window.addEventListener("resize", debounce(this.drawDiagram), 100); }, mounted() { this.drawDiagram(); }, computed: { ...mapState("fairwayavailability", [ "selectedFairwayAvailabilityFeature", "fwData", "from", "to", "frequency" ]), fromDate() { return this.from; }, toDate() { return this.to; }, availability() { return this.plainAvailability; }, title() { return `Available Fairway Depth: ${ this.featureName } (${filters.surveyDate(this.fromDate)} - ${filters.surveyDate( this.toDate )}) ${this.$gettext(this.frequency)}`; }, featureName() { return this.selectedFairwayAvailabilityFeature.properties.name; } }, methods: { close() { this.$store.commit("application/paneSetup", "DEFAULT"); }, drawDiagram() { this.dimensions = this.getDimensions(); this.yScale = d3 .scaleLinear() .domain([-33, 33]) .range([this.dimensions.mainHeight - 30, 0]); d3.select(".diagram-container svg").remove(); this.generateDiagramContainer(); this.drawBars(); this.drawScaleLabel(); this.drawScale(); }, generateDiagramContainer() { const diagram = d3 .select(".diagram-container") .append("svg") .attr("width", this.dimensions.width) .attr("height", this.dimensions.mainHeight); this.diagram = diagram .append("g") .attr("transform", `translate(0 ${this.paddingTop})`); }, drawBars() { const everyBar = this.diagram .selectAll("g") .data(this.fwData) .enter() .append("g") .attr("transform", (d, i) => { const dx = this.paddingRight + i * this.spaceBetween; return `translate(${dx})`; }); this.drawSingleBars(everyBar); this.drawLabelPerBar(everyBar); }, drawSingleBars(everyBar) { this.drawLDC(everyBar); this.drawHighestLevel(everyBar); this.drawLowerLevels(everyBar); }, drawLowerLevels(everyBar) { everyBar .selectAll("g") .data(d => d.lowerLevels.reverse()) .enter() .append("rect") .attr("y", this.yScale(0)) .attr("height", d => { return this.yScale(0) - this.yScale(hoursInDays(d)); }) .attr("width", this.barsWidth) .attr("fill", (d, i) => { return this.$options.COLORS.REST[i]; }); }, fnheight(name) { return d => this.yScale(0) - this.yScale(hoursInDays(d[name])); }, drawLDC(everyBar) { const height = this.fnheight("ldc"); everyBar .append("rect") .attr("y", this.yScale(0)) .attr("height", height) .attr("width", this.barsWidth) .attr("transform", d => `translate(0 ${-1 * height(d)})`) .attr("fill", this.$options.COLORS.LDC); }, drawHighestLevel(everyBar) { const height = this.fnheight("highestLevel"); everyBar .append("rect") .attr("y", this.yScale(0)) .attr("height", height) .attr("width", this.barsWidth) .attr("transform", d => `translate(0 ${-1 * height(d)})`) .attr("fill", this.$options.COLORS.HIGHEST); }, drawLabelPerBar(everyBar) { everyBar .append("text") .text(d => d.label) .attr("y", this.yScale(0) + this.labelPaddingTop); }, drawScaleLabel() { const center = this.dimensions.mainHeight / 2; this.diagram .append("text") .text(this.$options.LEGEND) .attr("text-anchor", "middle") .attr("x", 0) .attr("y", 0) .attr("dy", "1em") .attr("transform", `translate(0, ${center}), rotate(-90)`); }, drawScale() { const yAxis = d3.axisLeft().scale(this.yScale); this.diagram .append("g") .attr("transform", `translate(${this.scalePaddingLeft})`) .call(yAxis); } }, LEGEND: app.$gettext("sum of days / Summe der Tage"), COLORS: { LDC: "#59C6FF", HIGHEST: "#2D84B3", REST: ["#FF424F", "#FF737C", "#FF99A0"] } }; </script>