Mercurial > gemma
view client/src/components/gauge/Waterlevel.vue @ 2624:9dbaf69c7a66
Improve geoserver config to better calculate bounding boxes
* Disable the use of estimated extents for the postgis storage
configuration for geoserver, which is set via the gemma middleware.
This way we are able to get better bounding boxes for many layers
where the postgis function `ST_EstimatedExtent()` would be far off.
author | Bernhard Reiter <bernhard@intevation.de> |
---|---|
date | Wed, 13 Mar 2019 16:18:39 +0100 |
parents | e8c97481438f |
children | a735119e4f5c |
line wrap: on
line source
<template> <div class="flex-fill diagram-container"></div> </template> <style lang="sass" scoped> .diagram-container /deep/ .line stroke: steelblue stroke-width: 2 fill: transparent clip-path: url(#clip) .zoom cursor: move fill: none pointer-events: all .hdc-line, .ldc-line, .mw-line stroke-width: 1 fill: transparent clip-path: url(#clip) .hdc-line stroke: red .ldc-line stroke: green .mw-line stroke: grey .ref-waterlevel-label font-size: 11px fill: #999 .brush .selection stroke: transparent fill-opacity: 0.2 .handle fill: rgba($color-info, 0.5) </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): * Markus Kottländer <markus.kottlaender@intevation.de> */ import { mapState, mapGetters } from "vuex"; import * as d3 from "d3"; import debounce from "debounce"; export default { computed: { ...mapState("gauges", ["waterlevels"]), ...mapGetters("gauges", ["selectedGauge"]) }, watch: { waterlevels() { this.drawDiagram(); } }, methods: { drawDiagram() { if (!this.selectedGauge || !this.waterlevels.length) return; // remove old diagram d3.select(".diagram-container svg").remove(); // get HDC/LDC/MW of the gauge let refWaterLevels = JSON.parse( this.selectedGauge.properties.reference_water_levels ); // CREATE SVG AND SET DIMENSIONS/MARGINS let svgWidth = document.querySelector(".diagram-container").clientWidth; let svgHeight = document.querySelector(".diagram-container").clientHeight; let svg = d3 .select(".diagram-container") .append("svg") .attr("width", "100%") .attr("height", "100%"); let mainMargin = { top: 50, right: 20, bottom: 110, left: 40 }, navMargin = { top: svgHeight - mainMargin.top - 35, right: 20, bottom: 30, left: 40 }, width = +svgWidth - mainMargin.left - mainMargin.right, mainHeight = +svgHeight - mainMargin.top - mainMargin.bottom, navHeight = +svgHeight - navMargin.top - navMargin.bottom; // PREPARING AXES/SCALING // scaling helpers to convert real values to pixels // based on the diagrams dimensions let x = d3.scaleTime().range([0, width]), x2 = d3.scaleTime().range([0, width]), y = d3.scaleLinear().range([mainHeight, 0]), y2 = d3.scaleLinear().range([navHeight, 0]); // find min/max values for the waterlevel axis // including hdc/ldc (+/- 100 cm) let WaterlevelMinMax = d3.extent( [ ...this.waterlevels, { waterlevel: refWaterLevels.HDC + 100 }, { waterlevel: Math.max(refWaterLevels.LDC - 100, 0) } ], d => d.waterlevel ); // setting the min and max values for the diagram axes x.domain(d3.extent(this.waterlevels, d => d.date)); y.domain(WaterlevelMinMax); x2.domain(x.domain()); y2.domain(y.domain()); // creating the axes based on these scales let xAxis = d3.axisBottom(x), xAxis2 = d3.axisBottom(x2), yAxis = d3.axisLeft(y); // PREPARING CHART FUNCTIONS // waterlevel line in big chart let mainLineChart = d3 .line() .curve(d3.curveMonotoneX) .x(d => x(d.date)) .y(d => y(d.waterlevel)); // waterlevel line in small chart let navLineChart = d3 .line() .curve(d3.curveMonotoneX) .x(d => x2(d.date)) .y(d => y2(d.waterlevel)); // hdc/ldc/mw let refWaterlevelLine = d3 .line() .x(d => x(d.x)) .y(d => y(d.y)); // DRAWING MAINCHART // define visible area // everything outside this area will be hidden (clipped) svg .append("defs") .append("clipPath") .attr("id", "clip") .append("rect") .attr("width", width) .attr("height", mainHeight); let mainChart = svg .append("g") .attr("transform", `translate(${mainMargin.left}, ${mainMargin.top})`); // axes mainChart .append("g") .attr("transform", `translate(0, ${mainHeight})`) .call(xAxis); mainChart.append("g").call(yAxis); // waterlevel chart mainChart .append("path") .datum(this.waterlevels) .attr("class", "line") .attr("d", mainLineChart); // reference waterlevels let lastDate = this.waterlevels[this.waterlevels.length - 1].date; // HDC mainChart .append("path") .datum([ { x: 0, y: refWaterLevels.HDC }, { x: lastDate, y: refWaterLevels.HDC } ]) .attr("class", "hdc-line") .attr("d", refWaterlevelLine); mainChart // label .append("text") .text("HDC") .attr("class", "ref-waterlevel-label") .attr("x", x(lastDate) - 20) .attr("y", y(refWaterLevels.HDC) - 3); // LDC mainChart .append("path") .datum([ { x: 0, y: refWaterLevels.LDC }, { x: lastDate, y: refWaterLevels.LDC } ]) .attr("class", "ldc-line") .attr("d", refWaterlevelLine); mainChart // label .append("text") .text("LDC") .attr("class", "ref-waterlevel-label") .attr("x", x(lastDate) - 20) .attr("y", y(refWaterLevels.LDC) - 3); // MW mainChart .append("path") .datum([ { x: 0, y: refWaterLevels.MW }, { x: lastDate, y: refWaterLevels.MW } ]) .attr("class", "mw-line") .attr("d", refWaterlevelLine); mainChart // label .append("text") .text("MW") .attr("class", "ref-waterlevel-label") .attr("x", x(lastDate) - 20) .attr("y", y(refWaterLevels.MW) - 3); // DRAWING NAVCHART let navChart = svg .append("g") .attr("transform", `translate(${navMargin.left}, ${navMargin.top})`); // axis (nav chart only has y-axis) navChart .append("g") .attr("class", "axis axis--x") .attr("transform", `translate(0, ${navHeight})`) .call(xAxis2); // waterlevel chart navChart .append("path") .datum(this.waterlevels) .attr("class", "line") .attr("d", navLineChart); // INTERACTIVITY // selecting time period in nav chart let brush = d3 .brushX() .handleSize(4) .extent([[0, 0], [width, navHeight]]) .on("brush end", () => { if (d3.event.sourceEvent && d3.event.sourceEvent.type === "zoom") return; // ignore brush-by-zoom let s = d3.event.selection || x2.range(); x.domain(s.map(x2.invert, x2)); mainChart.select(".line").attr("d", mainLineChart); mainChart.select(".axis--x").call(xAxis); svg .select(".zoom") .call( zoom.transform, d3.zoomIdentity.scale(width / (s[1] - s[0])).translate(-s[0], 0) ); }); // zooming with mousewheel in main chart let zoom = d3 .zoom() .scaleExtent([1, Infinity]) .translateExtent([[0, 0], [width, mainHeight]]) .extent([[0, 0], [width, mainHeight]]) .on("zoom", () => { if (d3.event.sourceEvent && d3.event.sourceEvent.type === "brush") return; // ignore zoom-by-brush let t = d3.event.transform; x.domain(t.rescaleX(x2).domain()); mainChart.select(".line").attr("d", mainLineChart); mainChart.select(".axis--x").call(xAxis); navChart .select(".brush") .call(brush.move, x.range().map(t.invertX, t)); }); navChart .append("g") .attr("class", "brush") .call(brush) .call(brush.move, x.range()); svg .append("rect") .attr("class", "zoom") .attr("width", width) .attr("height", mainHeight) .attr("transform", `translate(${mainMargin.left}, ${mainMargin.top})`) .call(zoom); } }, created() { window.addEventListener("resize", debounce(this.drawDiagram), 100); }, mounted() { this.drawDiagram(); }, updated() { this.drawDiagram(); } }; </script>