Mercurial > gemma
comparison client/src/components/fairway/AvailableFairwayDepth.vue @ 3125:383720d8d98e
fairway_availability: generative code for diagram added
author | Thomas Junk <thomas.junk@intevation.de> |
---|---|
date | Mon, 29 Apr 2019 13:27:50 +0200 |
parents | c2c1e3e3af1c |
children | 1610d3042bbb |
comparison
equal
deleted
inserted
replaced
3124:583b6748431f | 3125:383720d8d98e |
---|---|
2 <div> | 2 <div> |
3 <h1>Available Fairway Depth</h1> | 3 <h1>Available Fairway Depth</h1> |
4 <UISpinnerOverlay v-if="loading" /> | 4 <UISpinnerOverlay v-if="loading" /> |
5 </div> | 5 </div> |
6 </template> | 6 </template> |
7 | |
8 <style></style> | |
7 | 9 |
8 <script> | 10 <script> |
9 /* This is Free Software under GNU Affero General Public License v >= 3.0 | 11 /* This is Free Software under GNU Affero General Public License v >= 3.0 |
10 * without warranty, see README.md and license for details. | 12 * without warranty, see README.md and license for details. |
11 * | 13 * |
23 import * as d3 from "d3"; | 25 import * as d3 from "d3"; |
24 | 26 |
25 export default { | 27 export default { |
26 data() { | 28 data() { |
27 return { | 29 return { |
28 plainAvailability: [], | |
29 loading: false | 30 loading: false |
30 }; | 31 }; |
31 }, | 32 }, |
32 computed: { | 33 computed: { |
33 availability() { | 34 availability() { |
34 return this.plainAvailability; | 35 return this.plainAvailability; |
35 } | 36 } |
36 }, | 37 }, |
37 methods: { | 38 methods: { |
38 /** | |
39 * | |
40 * aggregates data exceeding certain thresholds | |
41 * | |
42 * data = [1,2,3,4,5,6,7,8] | |
43 * treshold = [2,4,6] | |
44 * | |
45 * structure: treshold: count | |
46 * | |
47 * expected result = { | |
48 * 6: 2, | |
49 * 4: 2 | |
50 * 2: 2 | |
51 * } | |
52 * | |
53 * 1,2 are dropped, because they do not exceed any of the given tresholds | |
54 * | |
55 */ | |
56 availabeDaysPerMonth(data, tresholds) { | |
57 const DESC = (a, b) => { | |
58 if (a > b) return -1; | |
59 if (a === b) return 0; | |
60 return 1; | |
61 }; | |
62 const groups = tresholds.sort(DESC); | |
63 const collection = {}; | |
64 groups.map(g => { | |
65 collection[g + ""] = 0; | |
66 }); | |
67 return this.data.reduce((current, value) => { | |
68 for (let threshold in groups) { | |
69 if (value > threshold) { | |
70 return (current[threshold] += 1); | |
71 } | |
72 } | |
73 return current; | |
74 }, collection); | |
75 }, | |
76 drawDiagram() { | 39 drawDiagram() { |
77 const margin = 60; | 40 const width = 1000; |
78 const width = 1000 - 2 * margin; | 41 const height = 600; |
79 const height = 600 - 2 * margin; | 42 const data = [ |
43 { month: "feb", values: [30, 20, 10, 0] }, | |
44 { month: "mar", values: [25, 23, 0, 0] }, | |
45 { month: "apr", values: [17, 18, 16, 13] } | |
46 ]; | |
47 | |
80 const yScale = d3 | 48 const yScale = d3 |
81 .scaleLinear() | 49 .scaleLinear() |
82 .range([height, 0]) | 50 .domain([-30, 30]) |
83 .domain([-35, 35]); | 51 .range([height - 30, 0]); |
84 d3.select(".diagram-container svg").remove(); | 52 |
85 let svg = d3.select(".diagram-container").append("svg"); | 53 const diagram = d3 |
86 svg.attr("width", "100%"); | 54 .select("svg") |
87 svg.attr("height", "100%"); | 55 .attr("width", width) |
88 const chart = svg.attr("transform", `translate(${margin}, ${margin})`); | 56 .attr("height", height); |
89 chart.append("g").call(d3.axisLeft(yScale)); | 57 drawBars({ diagram, data, yScale }); |
90 const xScale = d3 | 58 drawLabel(diagram, height); |
91 .scaleBand() | 59 drawScale(diagram, yScale); |
92 .range([0, width]) | 60 }, |
93 .domain([1, 12]) | 61 drawBars({ diagram, data, yScale }) { |
94 .padding(0.2); | 62 const paddingRight = 100; |
95 chart | 63 const paddingTop = 30; |
64 | |
65 const bars = diagram | |
66 .selectAll("g") | |
67 .data(data) | |
68 .enter() | |
96 .append("g") | 69 .append("g") |
97 .attr("transform", `translate(0, ${height})`) | 70 .attr("transform", (d, i) => { |
98 .call(d3.axisBottom(xScale)); | 71 return ( |
99 chart | 72 "translate(" + (paddingRight + i * 60) + "," + yScale(-1) + ")" |
100 .selectAll() | 73 ); |
101 .data(this.availability) | 74 }); |
75 const bar = bars.append("g"); | |
76 | |
77 bar | |
78 .selectAll("rect") | |
79 .data(d => d.values) | |
102 .enter() | 80 .enter() |
103 .append("rect") | 81 .append("rect") |
104 .attr("x", s => xScale(s.month)) | 82 .attr("width", 30) |
105 .attr("y", s => yScale(s.days)) | 83 .attr("height", (d, i) => { |
106 .attr("height", s => height - yScale(s.days)) | 84 console.log(d); |
107 .attr("width", xScale.bandwidth()); | 85 return yScale(0) - yScale(d); |
86 }) | |
87 .attr("transform", d => { | |
88 return "translate(0 -" + (yScale(0) - yScale(d)) + ")"; | |
89 }) | |
90 .attr("fill", (d, i) => { | |
91 return colors[i]; | |
92 }); | |
93 | |
94 bars | |
95 .append("text") | |
96 .text((d, i) => { | |
97 return d.month; | |
98 }) | |
99 .attr("text-anchor", "middle") | |
100 .attr("x", 15) | |
101 .attr("y", 0) | |
102 .attr("dy", "1em"); | |
103 }, | |
104 drawLabel(diagram, height) { | |
105 const dy = height / 2; | |
106 diagram | |
107 .append("text") | |
108 .text("sum of days / Summe der Tage") | |
109 .attr("text-anchor", "middle") | |
110 .attr("x", 0) | |
111 .attr("y", 0) | |
112 .attr("dy", "1em") | |
113 .attr("transform", "translate(0, " + dy + "), rotate(-90)"); | |
114 }, | |
115 drawScale(diagram, yScale) { | |
116 const paddingLeft = 50; | |
117 const paddingTop = 10; | |
118 const yAxis = d3.axisLeft().scale(yScale); | |
119 diagram | |
120 .append("g") | |
121 .attr("transform", "translate(" + paddingLeft + " " + paddingTop + ")") | |
122 .call(yAxis); | |
108 } | 123 } |
109 } | 124 } |
110 }; | 125 }; |
111 </script> | 126 </script> |
112 | |
113 <style></style> |