My starting point for this question is the ability to print a map with a given format&resolution, very similar to the "Export to PDF" example at OpenLayers webpages: https://openlayers.org/en/latest/examples/export-pdf.html
I am not using the jsPDF library, but using similar approach of drawing to a printCanvas.
My challenge comes from when there is a measurement overlay in the map that should be printed. This is a screenshot from my map:
If I print my map "as is", meaning not changing format or resolution making sure the map size stays the same, everything is fine. I have created a canvas "renderer" of the overlay element, and this works decently.
However, when DPI/resolution or Format is modified, the size of the map changes. And hence I need to reposition my overlay.
My initial thought was that this shouldn't be too difficult, in my mind I wanted to implement it like this:
- Get the current position of the overlay in pixel coordinates.
- Calculate the ratio for width and height by taking new map size w/h and dividing it on old map size w/h
- "Translate" the old pixel coordinates to new pixel coordinates by multiplying them with the ratio
- Calculate the new actual coordinates by using the Map -> getCoordinateFromPixel() method
- Update the overlay position by using Overlay -> setPosition()
A simple small example on paper:
Old map size: 100w 100h
Old overlay position in pixels coords: 50,50
--- Increase map size by the double ---
New map size: 200w 200h
widthRatio = 2
heightRatio = 2
New overlay position in pixel coords: 100,100
However when I use my translated pixel coordinates, and update the position of my overlay, it does not render where it should:
In the example of the pictures I've gone from a map size of 1920w 956h to 2012w 1002h, so just a slight expansion of the map size.
I do believe that I know the reason for this, but I don't know how to handle it. I assume the problem is related to the fact that when map changes size - the viewport doesn't, so the getCoordinateFromPixel() is returning "wrong" coordinates for the new map size.
I verified this "assumption" by getting the line/geometry of the measure, and printing the geometry.getLastCoordinate() in pixel coordinates both before and after the map.setSize() method:
var size = [1920, 956];
var coord = getPixelFromCoordinate(geometry.getLastCoordinate())
coord with original map size 1920x956 = [1169,439]
//increase map size and set new resolution
var printSize = [2012, 1002];
map.setSize(printSize);
var scaling = Math.min(width / size[0], height / size[1]);
map.getView().setResolution(viewResolution / scaling);
//print pixel coordinates again
coord = getPixelFromCoordinate(geometry.getLastCoordinate())
coord with new map size 2012x1002 = [1169,439]
So despite the map size was increased, the pixel position is still the same for the feature - which I believe comes from the fact that the viewport did not change.
The API documentation for getPixelFromCoordinate() states "A pixel position in the map viewport." - so this is correct behavior I assume, but what can I do here to "translate" the position correctly according to the new map size?
If there is a simple apparent solution here I will apologize upfront for spending your time to read this, but I have made multiple attempts and not yet been able to find a solution to this.
Kind Regards,
Eivind Rønnevik