changeset 3980:7316b7e8246f pdfprint

improve PDFTool
author Thomas Junk <thomas.junk@intevation.de>
date Wed, 17 Jul 2019 12:28:25 +0200
parents 4eaa6bca367a
children 8ec8d9bc5468
files client/src/components/Pdftool.vue
diffstat 1 files changed, 134 insertions(+), 184 deletions(-) [+]
line wrap: on
line diff
--- a/client/src/components/Pdftool.vue	Wed Jul 17 10:47:11 2019 +0200
+++ b/client/src/components/Pdftool.vue	Wed Jul 17 12:28:25 2019 +0200
@@ -169,7 +169,7 @@
       readyToGenerate: true, // if the user is allowed to press the button
       rendercompleteListener: null,
       mapSize: null,
-      mapExtent: null
+      resolution: null
     };
   },
   computed: {
@@ -209,12 +209,6 @@
     close() {
       this.$store.commit("application/showPdfTool", false);
     },
-    millimeter2pixels(length, dpi) {
-      return (dpi * length) / 25.4;
-    },
-    pixel2millimeter(pixels, dpi) {
-      return (pixels * 25.4) / dpi;
-    },
     // When a template is chosen from the dropdown, its propoerties are
     // applied to the rest of the form.
     applyTemplateToForm() {
@@ -293,7 +287,7 @@
       // 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.
-      this.mapExtent = map.getView().calculateExtent(this.mapSize);
+      this.resolution = map.getView().getResolution();
 
       this.pdf.doc = new jsPDF(this.form.format, "mm", this.form.paperSize);
       // set a callback for after the next complete rendering of the map
@@ -315,191 +309,147 @@
           1000 * pixelsPerMapMillimeter * metersPerPixel
         );
         console.log("scaleDenominator = ", scaleDenominator);
-        const width80DPI = this.millimeter2pixels(this.pdf.width, 80);
-        const height80DPI = this.millimeter2pixels(this.pdf.height, 80);
-        const currentHeight = this.millimeter2pixels(
-          this.pdf.height,
-          this.form.resolution
-        );
-        const currentWidth = this.millimeter2pixels(
+        var snapshot = canvas.toDataURL("image/jpeg");
+        this.pdf.doc.addImage(
+          snapshot,
+          "JPEG",
+          0,
+          0,
           this.pdf.width,
-          this.form.resolution
+          this.pdf.height
         );
-        //const scaleFactor = this.form.resolution / 80;
-        var snapshot = canvas.toDataURL("image/jpeg");
-        const offscreen = document.createElement("canvas");
-        offscreen.width = currentWidth;
-        offscreen.height = currentHeight;
-        const image = new Image();
-        image.src = snapshot;
-        image.onload = () => {
-          offscreen
-            .getContext("2d")
-            .drawImage(
-              image,
-              (currentWidth - width80DPI) / 2,
-              (currentHeight - height80DPI) / 2,
-              width80DPI,
-              height80DPI,
-              0,
-              0,
-              currentWidth,
-              currentHeight
-            );
-          const data = offscreen.toDataURL("image/jpeg");
-          this.pdf.doc.addImage(
-            data,
-            "JPEG",
-            0,
-            0,
-            this.pdf.width,
-            this.pdf.height
-          );
 
-          if (this.templateData) {
-            this.pdf.doc.setFont("linbiolinum", "normal");
-            let defaultFontSize = 11,
-              defaultRounding = 2,
-              defaultTextColor = "black",
-              defaultBgColor = "white",
-              defaultPadding = 3,
-              defaultOffset = { x: 0, y: 0 },
-              defaultBorderColor = "white",
-              defaultWidth = 100;
-            this.templateData.elements.forEach(e => {
-              switch (e.type) {
-                case "text": {
-                  this.addText(
-                    e.position,
-                    e.offset || defaultOffset,
-                    e.width || defaultWidth,
-                    e.fontSize || defaultFontSize,
-                    e.color || defaultTextColor,
-                    e.text
-                  );
-                  break;
-                }
-                case "box": {
-                  this.addBox(
-                    e.position,
-                    e.offset || defaultOffset,
-                    e.width,
-                    e.height,
-                    // handling the case when the rectangle  not rounded (rounding = 0)
-                    e.rounding === 0 || e.rounding
-                      ? e.rounding
-                      : defaultRounding,
-                    e.color || defaultBgColor,
-                    e.brcolor || defaultBorderColor
-                  );
-                  break;
-                }
-                case "textbox": {
-                  this.addTextBox(
-                    e.position,
-                    e.offset || defaultOffset,
-                    e.width,
-                    e.height,
-                    e.rounding === 0 || e.rounding
-                      ? e.rounding
-                      : defaultRounding,
-                    e.padding || defaultPadding,
-                    e.fontSize || defaultFontSize,
-                    e.color || defaultTextColor,
-                    e.background || defaultBgColor,
-                    e.text,
-                    e.brcolor || defaultBorderColor
-                  );
-                  break;
-                }
-                case "image": {
-                  this.addImage(
-                    e.url,
-                    e.format,
-                    e.position,
-                    e.offset || defaultOffset,
-                    e.width,
-                    e.height
-                  );
-                  break;
-                }
-                case "bottleneck": {
-                  this.addBottleneckInfo(
-                    e.position,
-                    e.offset || defaultOffset,
-                    e.rounding === 0 || e.rounding
-                      ? e.rounding
-                      : defaultRounding,
-                    e.color || defaultTextColor,
-                    e.brcolor || defaultBorderColor
-                  );
-                  break;
-                }
-                case "legend": {
-                  this.addLegend(
-                    e.position,
-                    e.offset || defaultOffset,
-                    e.rounding === 0 || e.rounding
-                      ? e.rounding
-                      : defaultRounding,
-                    e.brcolor || defaultBorderColor
-                  );
-                  break;
-                }
-                case "scalebar": {
-                  this.addScaleBar(
-                    scaleDenominator,
-                    e.position,
-                    e.offset || defaultOffset,
-                    e.rounding === 0 || e.rounding
-                      ? e.rounding
-                      : defaultRounding,
-                    e.brcolor || defaultBorderColor
-                  );
-                  break;
-                }
-                case "scale": {
-                  this.addScale(
-                    scaleDenominator,
-                    e.position,
-                    e.width,
-                    e.offset || defaultOffset,
-                    e.fontSize || defaultFontSize,
-                    e.color || defaultTextColor
-                  );
-                  break;
-                }
-                case "northarrow": {
-                  this.addNorthArrow(
-                    e.position,
-                    e.offset || defaultOffset,
-                    e.size
-                  );
-                  break;
-                }
+        if (this.templateData) {
+          this.pdf.doc.setFont("linbiolinum", "normal");
+          let defaultFontSize = 11,
+            defaultRounding = 2,
+            defaultTextColor = "black",
+            defaultBgColor = "white",
+            defaultPadding = 3,
+            defaultOffset = { x: 0, y: 0 },
+            defaultBorderColor = "white",
+            defaultWidth = 100;
+          this.templateData.elements.forEach(e => {
+            switch (e.type) {
+              case "text": {
+                this.addText(
+                  e.position,
+                  e.offset || defaultOffset,
+                  e.width || defaultWidth,
+                  e.fontSize || defaultFontSize,
+                  e.color || defaultTextColor,
+                  e.text
+                );
+                break;
+              }
+              case "box": {
+                this.addBox(
+                  e.position,
+                  e.offset || defaultOffset,
+                  e.width,
+                  e.height,
+                  // handling the case when the rectangle  not rounded (rounding = 0)
+                  e.rounding === 0 || e.rounding ? e.rounding : defaultRounding,
+                  e.color || defaultBgColor,
+                  e.brcolor || defaultBorderColor
+                );
+                break;
+              }
+              case "textbox": {
+                this.addTextBox(
+                  e.position,
+                  e.offset || defaultOffset,
+                  e.width,
+                  e.height,
+                  e.rounding === 0 || e.rounding ? e.rounding : defaultRounding,
+                  e.padding || defaultPadding,
+                  e.fontSize || defaultFontSize,
+                  e.color || defaultTextColor,
+                  e.background || defaultBgColor,
+                  e.text,
+                  e.brcolor || defaultBorderColor
+                );
+                break;
               }
-            });
-
-            this.pdf.doc.save(this.filename);
-          }
-
-          // reset to original size
-          map.setSize(this.mapSize);
-          map.getView().fit(this.mapExtent, {
-            size: this.mapSize,
-            // necessary to get to the previous zoom level in all cases
-            // details see https://github.com/openlayers/openlayers/issues/9235
-            constrainResolution: false
+              case "image": {
+                this.addImage(
+                  e.url,
+                  e.format,
+                  e.position,
+                  e.offset || defaultOffset,
+                  e.width,
+                  e.height
+                );
+                break;
+              }
+              case "bottleneck": {
+                this.addBottleneckInfo(
+                  e.position,
+                  e.offset || defaultOffset,
+                  e.rounding === 0 || e.rounding ? e.rounding : defaultRounding,
+                  e.color || defaultTextColor,
+                  e.brcolor || defaultBorderColor
+                );
+                break;
+              }
+              case "legend": {
+                this.addLegend(
+                  e.position,
+                  e.offset || defaultOffset,
+                  e.rounding === 0 || e.rounding ? e.rounding : defaultRounding,
+                  e.brcolor || defaultBorderColor
+                );
+                break;
+              }
+              case "scalebar": {
+                this.addScaleBar(
+                  scaleDenominator,
+                  e.position,
+                  e.offset || defaultOffset,
+                  e.rounding === 0 || e.rounding ? e.rounding : defaultRounding,
+                  e.brcolor || defaultBorderColor
+                );
+                break;
+              }
+              case "scale": {
+                this.addScale(
+                  scaleDenominator,
+                  e.position,
+                  e.width,
+                  e.offset || defaultOffset,
+                  e.fontSize || defaultFontSize,
+                  e.color || defaultTextColor
+                );
+                break;
+              }
+              case "northarrow": {
+                this.addNorthArrow(
+                  e.position,
+                  e.offset || defaultOffset,
+                  e.size
+                );
+                break;
+              }
+            }
           });
 
-          // as we are done: re-enable button
-          this.readyToGenerate = true;
-        };
+          this.pdf.doc.save(this.filename);
+        }
+
+        // reset to original size
+        map.setSize(this.mapSize);
+        map.getView().setResolution(this.resolution);
+
+        // as we are done: re-enable button
+        this.readyToGenerate = true;
       });
 
       // trigger rendering
+      const size = map.getSize();
+      const [width, height] = mapSizeForPrint;
       map.setSize(mapSizeForPrint);
-      map.getView().fit(this.mapExtent, { size: mapSizeForPrint });
+      const scaling = Math.min(width / size[0], height / size[1]);
+      map.getView().setResolution(this.resolution / scaling);
     },
     cancel() {
       this.openLayersMap().un(
@@ -509,7 +459,7 @@
       this.openLayersMap().setSize(this.mapSize);
       this.openLayersMap()
         .getView()
-        .fit(this.mapExtent, { size: this.mapSize });
+        .fit(this.resolution, { size: this.mapSize });
       this.readyToGenerate = true;
     },
     // add the used map scale and papersize