changeset 3981:8ec8d9bc5468 pdfprint

document algorithm
author Thomas Junk <thomas.junk@intevation.de>
date Wed, 17 Jul 2019 12:48:19 +0200
parents 7316b7e8246f
children 5bae55d3966e
files client/src/components/Pdftool.vue
diffstat 1 files changed, 13 insertions(+), 33 deletions(-) [+]
line wrap: on
line diff
--- a/client/src/components/Pdftool.vue	Wed Jul 17 12:28:25 2019 +0200
+++ b/client/src/components/Pdftool.vue	Wed Jul 17 12:48:19 2019 +0200
@@ -244,7 +244,18 @@
       this.form.resolution = this.templateData.properties.resolution;
     },
     download() {
-      // disable button while working on it
+      /**
+       * In order to generate the image with the appropriate resolution
+       * we have to temporaily scale the visible part of the map.
+       * The newly rendered canvas is converted to Base64 DataURL.
+       * After that is done, the resolution is resetted to its previous state.
+       *
+       * calculateExtent() and fit() do not give the desired result
+       * when the view is rotated so we replace them completely by setting resolution
+       *
+       * Details: https://gis.stackexchange.com/questions/328933/openlayers-generating-clientside-pdfs
+       *
+       */
       this.readyToGenerate = false;
 
       console.log(
@@ -255,57 +266,33 @@
       );
 
       if (this.form.format !== "portrait") {
-        // landscape, default
         this.pdf.width = paperSizes[this.form.paperSize][0];
         this.pdf.height = paperSizes[this.form.paperSize][1];
       } else {
-        // switch width and height
         this.pdf.width = paperSizes[this.form.paperSize][1];
         this.pdf.height = paperSizes[this.form.paperSize][0];
       }
 
       // FUTURE: consider margins
 
-      // dots per mm = dots per inch / (25.4 mm/inch)
       var pixelsPerMapMillimeter = this.form.resolution / 25.4;
       var mapSizeForPrint = [
-        // in pixel
         Math.round(this.pdf.width * pixelsPerMapMillimeter),
         Math.round(this.pdf.height * pixelsPerMapMillimeter)
       ];
-
-      // generate PDF and open it
-      // our units are milimeters; width 0 x height 0 is left upper corner
-
-      // Step 1 prepare and save current map extend
-      // Then add callback "rendercomplete" for Step 3
-      //    which will generate the pdf and resets the map view
-      // Step 2 which starts rendering a map with the necessary image size
-
       var map = this.openLayersMap();
-      this.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.
+      this.mapSize = map.getSize();
       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
       this.rendercompleteListener = map.once("rendercomplete", event => {
         let canvas = event.context.canvas;
-
-        // because we are using Web Mercator, a pixel represents
-        // a differently sized spot depending on the place of the map.
-        // So we use a value calculated from the center of the current view.
         let view = map.getView();
         let proj = view.getProjection();
         let metersPerPixel = // average meters (reality) per pixel (map)
           getPointResolution(proj, view.getResolution(), view.getCenter()) *
           proj.getMetersPerUnit();
-        // DEBUG console.log("metersPerPixel = ", metersPerPixel);
-
         let scaleDenominator = Math.round(
-          // the x in 1:x map scale
           1000 * pixelsPerMapMillimeter * metersPerPixel
         );
         console.log("scaleDenominator = ", scaleDenominator);
@@ -348,7 +335,6 @@
                   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
@@ -435,16 +421,10 @@
 
           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);