Mercurial > gemma
comparison client/src/components/fairway/AvailableFairwayDepth.vue @ 3267:b07b4cca5e34
client: diagram-template: implement pdf-template for fairway availability diagram
* implement default template
* add some template elements
* fit d3-styles to get renderd on pdf
author | Fadi Abbud <fadi.abbud@intevation.de> |
---|---|
date | Wed, 15 May 2019 13:18:33 +0200 |
parents | a7d44d1ae57d |
children | 1a97a079ef1b |
comparison
equal
deleted
inserted
replaced
3266:3dee5cf16a58 | 3267:b07b4cca5e34 |
---|---|
12 :key="index" | 12 :key="index" |
13 > | 13 > |
14 {{ entry }} | 14 {{ entry }} |
15 </li> | 15 </li> |
16 </ul> | 16 </ul> |
17 <div class="my-auto mx-auto"> | |
18 <select | |
19 v-model="form.template" | |
20 class="form-control d-block custom-select-sm w-100 mt-1" | |
21 > | |
22 <option | |
23 v-for="template in templates" | |
24 :value="template" | |
25 :key="template.name" | |
26 > | |
27 {{ template.name }} | |
28 </option> | |
29 </select> | |
30 <button | |
31 @click="downloadPDF" | |
32 type="button" | |
33 class="btn btn-sm btn-info d-block w-100 mt-1" | |
34 > | |
35 <translate>Export to PDF</translate> | |
36 </button> | |
37 </div> | |
17 </div> | 38 </div> |
18 <div :id="containerId" class="mx-auto my-auto diagram-container"></div> | 39 <div |
40 ref="diagramContainer" | |
41 :id="containerId" | |
42 class="mx-auto my-auto diagram-container" | |
43 ></div> | |
19 </div> | 44 </div> |
20 </div> | 45 </div> |
21 </template> | 46 </template> |
22 | 47 |
23 <style></style> | 48 <style></style> |
41 import app from "@/main"; | 66 import app from "@/main"; |
42 import debounce from "debounce"; | 67 import debounce from "debounce"; |
43 import { diagram } from "@/lib/mixins"; | 68 import { diagram } from "@/lib/mixins"; |
44 import { mapState } from "vuex"; | 69 import { mapState } from "vuex"; |
45 import filters from "@/lib/filters.js"; | 70 import filters from "@/lib/filters.js"; |
71 import jsPDF from "jspdf"; | |
72 import canvg from "canvg"; | |
73 import { pdfgen } from "@/lib/mixins"; | |
46 | 74 |
47 const hoursInDays = x => x / 24; | 75 const hoursInDays = x => x / 24; |
48 | 76 |
49 export default { | 77 export default { |
50 mixins: [diagram], | 78 mixins: [diagram, pdfgen], |
51 data() { | 79 data() { |
52 return { | 80 return { |
53 containerId: "availablefairwaydepth", | 81 containerId: "availablefairwaydepth", |
54 loading: false, | 82 loading: false, |
55 width: 1000, | 83 width: 1000, |
60 scalePaddingLeft: 50, | 88 scalePaddingLeft: 50, |
61 paddingTop: 10, | 89 paddingTop: 10, |
62 diagram: null, | 90 diagram: null, |
63 yScale: null, | 91 yScale: null, |
64 barsWidth: 60, | 92 barsWidth: 60, |
65 dimensions: null | 93 dimensions: null, |
94 pdf: { | |
95 doc: null, | |
96 width: null, | |
97 height: null | |
98 }, | |
99 form: { | |
100 template: null | |
101 }, | |
102 templateData: null, | |
103 templates: [], | |
104 defaultemplate: { | |
105 name: "Default", | |
106 properties: { | |
107 paperSize: "a4" | |
108 }, | |
109 elements: [ | |
110 { | |
111 type: "diagram", | |
112 position: "topleft", | |
113 offset: { x: 20, y: 60 }, | |
114 width: 290, | |
115 height: 100 | |
116 }, | |
117 { | |
118 type: "diagramtitle", | |
119 position: "topleft", | |
120 offset: { x: 20, y: 20 }, | |
121 fontsize: 20, | |
122 color: "steelblue" | |
123 }, | |
124 { | |
125 type: "diagramlegend", | |
126 position: "topleft", | |
127 offset: { x: 30, y: 160 }, | |
128 color: "black" | |
129 } | |
130 ] | |
131 } | |
66 }; | 132 }; |
67 }, | 133 }, |
68 created() { | 134 created() { |
69 window.addEventListener("resize", debounce(this.drawDiagram), 100); | 135 window.addEventListener("resize", debounce(this.drawDiagram), 100); |
70 }, | 136 }, |
71 mounted() { | 137 mounted() { |
72 this.drawDiagram(); | 138 this.drawDiagram(); |
139 this.templates[0] = this.defaultemplate; | |
140 this.form.template = this.templates[0]; | |
141 this.templateData = this.templates[0]; | |
73 }, | 142 }, |
74 computed: { | 143 computed: { |
75 ...mapState("fairwayavailability", [ | 144 ...mapState("fairwayavailability", [ |
76 "selectedFairwayAvailabilityFeature", | 145 "selectedFairwayAvailabilityFeature", |
77 "fwData", | 146 "fwData", |
92 title() { | 161 title() { |
93 return `Available Fairway Depth: ${ | 162 return `Available Fairway Depth: ${ |
94 this.featureName | 163 this.featureName |
95 } (${filters.surveyDate(this.fromDate)} - ${filters.surveyDate( | 164 } (${filters.surveyDate(this.fromDate)} - ${filters.surveyDate( |
96 this.toDate | 165 this.toDate |
97 )}) ${this.$gettext(this.frequency)}`; | 166 )}) ${this.$gettext(this.fre40quency)}`; |
98 }, | 167 }, |
99 featureName() { | 168 featureName() { |
100 return this.selectedFairwayAvailabilityFeature.properties.name; | 169 return this.selectedFairwayAvailabilityFeature.properties.name; |
101 } | 170 } |
102 }, | 171 }, |
103 methods: { | 172 methods: { |
173 downloadPDF() { | |
174 this.pdf.doc = new jsPDF( | |
175 "l", | |
176 "mm", | |
177 this.templateData.properties.paperSize | |
178 ); | |
179 // pdf width and height in millimeter (landscape) | |
180 this.pdf.width = | |
181 this.templateData.properties.paperSize === "a3" ? 420 : 297; | |
182 this.pdf.height = | |
183 this.templateData.properties.paperSize === "a3" ? 297 : 210; | |
184 if (this.templateData) { | |
185 let defaultOffset = { x: 0, y: 0 }, | |
186 defaultFontSize = 10, | |
187 defaultColor = "black"; | |
188 this.templateData.elements.forEach(e => { | |
189 switch (e.type) { | |
190 case "diagram": { | |
191 this.addDiagram( | |
192 e.position, | |
193 e.offset || defaultOffset, | |
194 e.width, | |
195 e.height | |
196 ); | |
197 break; | |
198 } | |
199 case "diagramtitle": { | |
200 this.addDiagramTitle( | |
201 e.position, | |
202 e.offset || defaultOffset, | |
203 e.fontsize || defaultFontSize, | |
204 e.color || defaultColor | |
205 ); | |
206 break; | |
207 } | |
208 case "diagramlegend": { | |
209 this.addDiagramLegend( | |
210 e.position, | |
211 e.offset || defaultOffset, | |
212 e.color || defaultColor | |
213 ); | |
214 } | |
215 } | |
216 }); | |
217 } | |
218 this.pdf.doc.save(`Available Fairway Depth: ${this.featureName}`); | |
219 }, | |
220 addDiagram(position, offset, width, height) { | |
221 let x = offset.x, | |
222 y = offset.y; | |
223 var svg = this.$refs.diagramContainer.innerHTML; | |
224 if (svg) { | |
225 svg = svg.replace(/\r?\n|\r/g, "").trim(); | |
226 } | |
227 if (!width) { | |
228 width = this.templateData.properties.paperSize === "a3" ? 380 : 290; | |
229 } | |
230 if (!height) { | |
231 height = this.templateData.properties.paperSize === "a3" ? 130 : 100; | |
232 } | |
233 if (["topright", "bottomright"].indexOf(position) !== -1) { | |
234 x = this.pdf.width - offset.x - width; | |
235 } | |
236 if (["bottomright", "bottomleft"].indexOf(position) !== -1) { | |
237 y = this.pdf.height - offset.y - height; | |
238 } | |
239 var canvas = document.createElement("canvas"); | |
240 canvas.width = window.innerWidth; | |
241 canvas.height = window.innerHeight / 2; | |
242 canvg(canvas, svg, { | |
243 ignoreMouse: true, | |
244 ignoreAnimation: true, | |
245 ignoreDimensions: true | |
246 }); | |
247 var imgData = canvas.toDataURL("image/png"); | |
248 this.pdf.doc.addImage(imgData, "PNG", x, y, width, height); | |
249 }, | |
250 addDiagramTitle(position, offset, size, color) { | |
251 let x = offset.x, | |
252 y = offset.y; | |
253 let title = this.title; | |
254 let width = | |
255 (this.pdf.doc.getStringUnitWidth(title) * size) / (72 / 25.6) + | |
256 size / 2; | |
257 // if position is on the right, x needs to be calculate with pdf width and | |
258 // the size of the element | |
259 if (["topright", "bottomright"].indexOf(position) !== -1) { | |
260 x = this.pdf.width - offset.x - width; | |
261 } | |
262 if (["bottomright", "bottomleft"].indexOf(position) !== -1) { | |
263 y = this.pdf.height - offset.y - this.getTextHeight(1); | |
264 } | |
265 this.pdf.doc.setTextColor(color); | |
266 this.pdf.doc.setFontSize(size); | |
267 this.pdf.doc.setFontStyle("bold"); | |
268 this.pdf.doc.text(title, x, y, { baseline: "hanging" }); | |
269 }, | |
270 addDiagramLegend(position, offset, color) { | |
271 let x = offset.x, | |
272 y = offset.y; | |
273 | |
274 this.pdf.doc.setFontSize(10); | |
275 this.pdf.doc.setTextColor(color); | |
276 this.pdf.doc.setDrawColor("rgb(255, 133, 94)"); | |
277 this.pdf.doc.setFillColor("rgb(255, 133, 94)"); | |
278 this.pdf.doc.rect(x, y, 8, 4, "FD"); | |
279 this.pdf.doc.text(">= LDC [h]", x + 10, y + 3); | |
280 | |
281 this.pdf.doc.setDrawColor("rgb(255, 66, 79)"); | |
282 this.pdf.doc.setFillColor("rgb(255, 66, 79)"); | |
283 this.pdf.doc.rect(x, y + 5, 8, 4, "FD"); | |
284 this.pdf.doc.text("< 200.00 [h]", x + 10, y + 8); | |
285 | |
286 this.pdf.doc.setDrawColor("rgb(255, 115, 124)"); | |
287 this.pdf.doc.setFillColor("rgb(255, 115, 124)"); | |
288 this.pdf.doc.rect(x, y + 10, 8, 4, "FD"); | |
289 this.pdf.doc.text(">= 200.00 [h]", x + 10, y + 13); | |
290 | |
291 this.pdf.doc.setDrawColor("rgb(255, 153, 160)"); | |
292 this.pdf.doc.setFillColor("rgb(255, 153, 160)"); | |
293 this.pdf.doc.rect(x, y + 15, 8, 4, "FD"); | |
294 this.pdf.doc.text(">= 230.00 [h]", x + 10, y + 18); | |
295 | |
296 this.pdf.doc.setDrawColor("rgb(45, 132, 179)"); | |
297 this.pdf.doc.setFillColor("rgb(45, 132, 179)"); | |
298 this.pdf.doc.rect(x, y + 20, 8, 4, "FD"); | |
299 this.pdf.doc.text(">= 250.00 [h]", x + 10, y + 23); | |
300 }, | |
104 legendStyle(index) { | 301 legendStyle(index) { |
105 if (index == 0) return `background-color: ${this.$options.COLORS.LDC};`; | 302 if (index == 0) return `background-color: ${this.$options.COLORS.LDC};`; |
106 if (index < 4) | 303 if (index < 4) |
107 return `background-color: ${this.$options.COLORS.REST[index - 1]};`; | 304 return `background-color: ${this.$options.COLORS.REST[index - 1]};`; |
108 return `background-color: ${this.$options.COLORS.HIGHEST};`; | 305 return `background-color: ${this.$options.COLORS.HIGHEST};`; |
211 drawScale() { | 408 drawScale() { |
212 const yAxis = d3.axisLeft().scale(this.yScale); | 409 const yAxis = d3.axisLeft().scale(this.yScale); |
213 this.diagram | 410 this.diagram |
214 .append("g") | 411 .append("g") |
215 .attr("transform", `translate(${this.scalePaddingLeft})`) | 412 .attr("transform", `translate(${this.scalePaddingLeft})`) |
216 .call(yAxis); | 413 .call(yAxis) |
414 .selectAll(".tick text") | |
415 .attr("fill", "black") | |
416 .select(function() { | |
417 return this.parentNode; | |
418 }) | |
419 .selectAll(".tick line") | |
420 .attr("stroke", "black"); | |
421 this.diagram.selectAll(".domain").attr("stroke", "black"); | |
217 } | 422 } |
218 }, | 423 }, |
219 LEGEND: app.$gettext("Sum of days"), | 424 LEGEND: app.$gettext("Sum of days"), |
220 COLORS: { | 425 COLORS: { |
221 LDC: "#FF855E", | 426 LDC: "#FF855E", |