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);
     }
   }
 };