Mercurial > gemma
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);