Mercurial > gemma
changeset 1876:e53924abb4a2 dev-pdf-generation
client: export some elements to pdf
* render north arrow, scale bar and text on pdf
author | Fadi Abbud <fadi.abbud@intevation.de> |
---|---|
date | Wed, 09 Jan 2019 15:59:33 +0100 |
parents | cc8592bf489b |
children | 46d007e3de2d |
files | client/src/components/Pdftool.vue |
diffstat | 1 files changed, 126 insertions(+), 25 deletions(-) [+] |
line wrap: on
line diff
--- a/client/src/components/Pdftool.vue Tue Jan 08 16:16:22 2019 +0100 +++ b/client/src/components/Pdftool.vue Wed Jan 09 15:59:33 2019 +0100 @@ -1,4 +1,5 @@ -<template> + + <template> <div :class="[ 'box ui-element rounded bg-white text-nowrap', @@ -7,8 +8,8 @@ > <div style="width: 20rem"> <h6 class="mb-0 py-2 px-3 border-bottom d-flex align-items-center"> - <font-awesome-icon icon="file-pdf" class="mr-2"></font-awesome-icon - ><translate>Generate PDF</translate> + <font-awesome-icon icon="file-pdf" class="mr-2"></font-awesome-icon> + <translate>Generate PDF</translate> <font-awesome-icon icon="times" class="ml-auto text-muted" @@ -16,14 +17,24 @@ ></font-awesome-icon> </h6> <div class="p-3"> - <b><translate>Chose format:</translate></b> + <b> + <translate>Chose format:</translate> + </b> <select v-model="form.format" class="form-control d-block w-100"> - <option value="landscape"><translate>landscape</translate></option> - <option value="portrait"><translate>portrait</translate></option> + <option value="landscape"> + <translate>landscape</translate> + </option> + <option value="portrait"> + <translate>portrait</translate> + </option> </select> <select v-model="form.paperSize" class="form-control d-block w-100"> - <option value="a3"><translate>ISO A3</translate></option> - <option value="a4"><translate>ISO A4</translate></option> + <option value="a3"> + <translate>ISO A3</translate> + </option> + <option value="a4"> + <translate>ISO A4</translate> + </option> </select> <small class="d-block my-2"> <input @@ -32,25 +43,21 @@ value="download" v-model="form.downloadType" selected - /> - <label for="pdfexport-downloadtype-download" class="ml-1 mr-2" - ><translate>Download</translate></label > + <label for="pdfexport-downloadtype-download" class="ml-1 mr-2"> + <translate>Download</translate> + </label> <input type="radio" id="pdfexport-downloadtype-open" value="open" v-model="form.downloadType" - /> - <label for="pdfexport-downloadtype-open" class="ml-1" - ><translate>Open in new window</translate></label > + <label for="pdfexport-downloadtype-open" class="ml-1"> + <translate>Open in new window</translate> + </label> </small> - <button - @click="download" - type="button" - class="btn btn-sm btn-info d-block w-100" - > + <button @click="download" type="button" class="btn btn-sm btn-info d-block w-100"> <translate>Generate PDF</translate> </button> </div> @@ -106,7 +113,6 @@ this.form.paperSize, this.form.format ); - var width, height; // generate PDF and open it if (this.form.format !== "portrait") { @@ -126,23 +132,32 @@ var map = this.openLayersMap; var mapSize = map.getSize(); // size in pixels of the map in the DOM - // Calculate the extent for the current view state and the passed size. // The size is the pixel dimensions of the box into which the calculated // extent should fit. var mapExtent = map.getView().calculateExtent(mapSize); - var pdf = new jsPDF(this.form.format, "mm", this.form.paperSize); - + var self = this; + var scalebarSize = + self.form.format === "portrait" && self.form.paperSize === "a4" + ? 10 + : 15; + var northarrowSize = 3; // set a callback for after the next complete rendering of the map map.once("rendercomplete", function(event) { let canvas = event.context.canvas; console.log("rendered", canvas); var data = canvas.toDataURL("image/png"); pdf.addImage(data, "PNG", 0, 0, width, height); - + self.addScalebar( + pdf, + width - scalebarSize * 5, + height - scalebarSize / 2, + scalebarSize + ); + //self.addText(pdf, 150, 20, 10, "black", 70, "some text"); + self.addNorthArrow(pdf, 15, 8, northarrowSize); pdf.save("map.pdf"); - // reset to original size map.setSize(mapSize); map.getView().fit(mapExtent, { size: mapSize }); @@ -176,6 +191,92 @@ a.click(); document.body.removeChild(a); */ + }, + + addScalebar(doc, x, y, size) { + doc.setDrawColor(255, 255, 255); + doc.setFillColor(255, 255, 255); + doc.roundedRect(x - size / 2, y - size / 2, size * 5, size, 3, 3, "FD"); + doc.setDrawColor(0, 0, 0); + doc.setFillColor(0, 0, 0); + doc.rect(x, y, size, 1, "FD"); + doc.setFillColor(255, 255, 255); + doc.setDrawColor(0, 0, 0); + doc.rect(x + size, y, size, 1, "FD"); + doc.setFillColor(0, 0, 0); + doc.setDrawColor(0, 0, 0); + doc.rect(x + size * 2, y, size * 2, 1, "FD"); + doc.setFontSize(5); + doc.text(x, y + 3, "0"); + doc.text(x + size, y + 3, "50"); + doc.text(x + size * 2, y + 3, "100"); + doc.text(x + size * 4, y + 3, "200 m"); + }, + + addNorthArrow(doc, x1, y1, size) { + var y2 = y1 + size * 3; + var x3 = x1 - size * 2; + var y3 = y1 + size * 5; + var x4 = x1 + size * 2; + //white triangle + doc.setFillColor(255, 255, 255); + doc.setDrawColor(255, 255, 255); + doc.triangle(x3 - 0.8, y3 + 1.2, x1, y1 - 1.2, x1, y2 + 0.6, "F"); + doc.triangle(x1, y1 - 1.2, x1, y2 + 0.6, x4 + 0.8, y3 + 1.2, "F"); + //north arrow + doc.setDrawColor(0, 0, 0); + doc.setFillColor(255, 255, 255); + doc.triangle(x3, y3, x1, y1, x1, y2, "FD"); + doc.setFillColor(0, 0, 0); + doc.triangle(x1, y1, x1, y2, x4, y3, "FD"); + doc.setFontSize(size * 3.1); + doc.setTextColor(255, 255, 255); + doc.setFontStyle("bold"); + doc.text(size < 3 ? x1 - 0.5 : x1 - 1.3, y3 + 1, "N"); + doc.setFontSize(size * 3); + doc.setTextColor(0, 0, 0); + doc.setFontStyle("normal"); + doc.text(size < 3 ? x1 - 0.5 : x1 - 1.3, y3 + 1, "N"); + }, + + //export an image to PDF + addImage(doc, img, type, x, y, width, hight) { + doc.addImage(img, type, x, y, width, hight); + }, + + // add some text at specific coordinates and determine how many wrolds in single line + addText(doc, postitionX, positionY, size, color, lineWidth, text) { + // split the incoming string to an array, each element is a string of words in a single line + var textLines = doc.splitTextToSize(text, lineWidth); + // get the longest line to fit the white backround to it + var longestString = ""; + textLines.forEach(function(element) { + if (element.length > longestString.length) longestString = element; + }); + var indexOfMaxString = textLines.indexOf(longestString); + // white background (rectangular) around the text + doc.setFillColor(255, 255, 255); + doc.setDrawColor(255, 255, 255); + doc.rect( + postitionX - doc.getStringUnitWidth(textLines[indexOfMaxString]) / size, + size > 10 ? positionY - size / 1.8 : positionY - size / 2.4, + doc.getStringUnitWidth(textLines[indexOfMaxString]) * (size / 2.6), + textLines.length * (size / 2), + "FD" + ); + //rounded rectangular + /* doc.roundedRect( + postitionX - doc.getStringUnitWidth(textLines[indexOfMaxString]) / size, + size > 10 ? positionY - size / 1.8 : positionY - size / 2.6, + doc.getStringUnitWidth(textLines[indexOfMaxString]) * (size / 2.6), + textLines.length * (size / 2), + 3, + 3, + "FD" + ); */ + doc.setTextColor(color); + doc.setFontSize(size); + doc.text(postitionX, positionY, textLines); } } };