Mercurial > gemma
comparison client/src/components/gauge/Waterlevel.vue @ 2684:c4da269238a4
client: waterlevel diagram: visualize data gaps
author | Markus Kottlaender <markus@intevation.de> |
---|---|
date | Fri, 15 Mar 2019 12:43:30 +0100 |
parents | 7fd47d9641ac |
children | 8f919fe629f9 |
comparison
equal
deleted
inserted
replaced
2680:bd615f978164 | 2684:c4da269238a4 |
---|---|
3 </template> | 3 </template> |
4 | 4 |
5 <style lang="sass" scoped> | 5 <style lang="sass" scoped> |
6 .diagram-container | 6 .diagram-container |
7 /deep/ | 7 /deep/ |
8 .line | 8 .main |
9 stroke: steelblue | 9 .line |
10 stroke-width: 2 | 10 clip-path: url(#clip) |
11 fill: transparent | 11 .nav |
12 clip-path: url(#clip) | 12 .line |
13 stroke: steelblue | |
14 stroke-width: 2 | |
15 fill: transparent | |
16 clip-path: url(#clip) | |
13 | 17 |
14 .hdc-line, | 18 .hdc-line, |
15 .ldc-line, | 19 .ldc-line, |
16 .mw-line | 20 .mw-line |
17 stroke-width: 1 | 21 stroke-width: 1 |
61 * Author(s): | 65 * Author(s): |
62 * Markus Kottländer <markus.kottlaender@intevation.de> | 66 * Markus Kottländer <markus.kottlaender@intevation.de> |
63 */ | 67 */ |
64 | 68 |
65 import { mapState, mapGetters } from "vuex"; | 69 import { mapState, mapGetters } from "vuex"; |
66 import * as d3 from "d3"; | 70 import * as d3Base from "d3"; |
71 import { lineChunked } from "d3-line-chunked"; | |
67 import debounce from "debounce"; | 72 import debounce from "debounce"; |
73 | |
74 // we should load only d3 modules we need but for now we'll go with the lazy way | |
75 // https://www.giacomodebidda.com/how-to-import-d3-plugins-with-webpack/ | |
76 const d3 = Object.assign(d3Base, { lineChunked }); | |
68 | 77 |
69 export default { | 78 export default { |
70 computed: { | 79 computed: { |
71 ...mapState("gauges", ["waterlevels"]), | 80 ...mapState("gauges", ["waterlevels"]), |
72 ...mapGetters("gauges", ["selectedGauge"]) | 81 ...mapGetters("gauges", ["selectedGauge"]) |
143 .tickSizeOuter(0); | 152 .tickSizeOuter(0); |
144 | 153 |
145 // PREPARING CHART FUNCTIONS | 154 // PREPARING CHART FUNCTIONS |
146 | 155 |
147 // waterlevel line in big chart | 156 // waterlevel line in big chart |
148 let mainLineChart = d3 | 157 // d3-line-chunked plugin: https://github.com/pbeshai/d3-line-chunked |
149 .line() | 158 var mainLineChart = d3 |
150 .curve(d3.curveMonotoneX) | 159 .lineChunked() |
151 .x(d => x(d.date)) | 160 .x(d => x(d.date)) |
152 .y(d => y(d.waterlevel)); | 161 .y(d => y(d.waterlevel)) |
162 .curve(d3.curveLinear) | |
163 .isNext((prev, current) => { | |
164 // points are "next to each other" when they are exactly 15 minutes apart | |
165 return current.date - prev.date === 15 * 60 * 1000; | |
166 }) | |
167 .lineStyles({ stroke: "steelblue" }) | |
168 .gapStyles({ | |
169 stroke: "steelblue", | |
170 "stroke-opacity": 1, | |
171 "stroke-dasharray": "3 3", | |
172 "stroke-width": 1 | |
173 }); | |
153 // waterlevel line in small chart | 174 // waterlevel line in small chart |
154 let navLineChart = d3 | 175 let navLineChart = d3 |
155 .line() | 176 .line() |
156 .curve(d3.curveMonotoneX) | 177 .curve(d3.curveMonotoneX) |
157 .x(d => x2(d.date)) | 178 .x(d => x2(d.date)) |
174 .attr("width", width) | 195 .attr("width", width) |
175 .attr("height", mainHeight); | 196 .attr("height", mainHeight); |
176 | 197 |
177 let mainChart = svg | 198 let mainChart = svg |
178 .append("g") | 199 .append("g") |
200 .attr("class", "main") | |
179 .attr("transform", `translate(${mainMargin.left}, ${mainMargin.top})`); | 201 .attr("transform", `translate(${mainMargin.left}, ${mainMargin.top})`); |
180 | 202 |
181 // axes | 203 // axes |
182 mainChart | 204 mainChart |
183 .append("g") | 205 .append("g") |
254 .attr("x", x(lastDate) - 20) | 276 .attr("x", x(lastDate) - 20) |
255 .attr("y", y(refWaterLevels.MW) - 3); | 277 .attr("y", y(refWaterLevels.MW) - 3); |
256 | 278 |
257 // waterlevel chart | 279 // waterlevel chart |
258 mainChart | 280 mainChart |
259 .append("path") | 281 .append("g") |
282 .attr("class", "line") | |
260 .datum(this.waterlevels) | 283 .datum(this.waterlevels) |
261 .attr("class", "line") | 284 .transition() |
262 .attr("d", mainLineChart); | 285 .duration(1000) |
286 .call(mainLineChart); | |
263 | 287 |
264 // DRAWING NAVCHART | 288 // DRAWING NAVCHART |
265 | 289 |
266 let navChart = svg | 290 let navChart = svg |
267 .append("g") | 291 .append("g") |
292 .attr("class", "nav") | |
268 .attr("transform", `translate(${navMargin.left}, ${navMargin.top})`); | 293 .attr("transform", `translate(${navMargin.left}, ${navMargin.top})`); |
269 | 294 |
270 // axis (nav chart only has y-axis) | 295 // axis (nav chart only has y-axis) |
271 navChart | 296 navChart |
272 .append("g") | 297 .append("g") |
291 .on("brush end", () => { | 316 .on("brush end", () => { |
292 if (d3.event.sourceEvent && d3.event.sourceEvent.type === "zoom") | 317 if (d3.event.sourceEvent && d3.event.sourceEvent.type === "zoom") |
293 return; // ignore brush-by-zoom | 318 return; // ignore brush-by-zoom |
294 let s = d3.event.selection || x2.range(); | 319 let s = d3.event.selection || x2.range(); |
295 x.domain(s.map(x2.invert, x2)); | 320 x.domain(s.map(x2.invert, x2)); |
296 mainChart.select(".line").attr("d", mainLineChart); | 321 mainChart.select(".line").call(mainLineChart); |
297 mainChart | 322 mainChart |
298 .select(".axis--x") | 323 .select(".axis--x") |
299 .call(xAxis) | 324 .call(xAxis) |
300 .selectAll(".tick text") | 325 .selectAll(".tick text") |
301 .attr("y", 15); | 326 .attr("y", 15); |
316 .on("zoom", () => { | 341 .on("zoom", () => { |
317 if (d3.event.sourceEvent && d3.event.sourceEvent.type === "brush") | 342 if (d3.event.sourceEvent && d3.event.sourceEvent.type === "brush") |
318 return; // ignore zoom-by-brush | 343 return; // ignore zoom-by-brush |
319 let t = d3.event.transform; | 344 let t = d3.event.transform; |
320 x.domain(t.rescaleX(x2).domain()); | 345 x.domain(t.rescaleX(x2).domain()); |
321 mainChart.select(".line").attr("d", mainLineChart); | 346 mainChart.select(".line").call(mainLineChart); |
322 mainChart | 347 mainChart |
323 .select(".axis--x") | 348 .select(".axis--x") |
324 .call(xAxis) | 349 .call(xAxis) |
325 .selectAll(".tick text") | 350 .selectAll(".tick text") |
326 .attr("y", 15); | 351 .attr("y", 15); |