2

I understand that the canvas.toDataURL function will only export at 96dpi and that I need to increase the canvas size in order to get the desired output scale at say 300dpi.

This question has a great dpi function in answer 2: Higher DPI graphics with HTML5 canvas

I am using the following code to export a OpenLayers3 map as a png image file when a button is pressed - button contained within an a tag:

<a download="map.png" id='export-png'">


      function setDPI(canvas, dpi) {
       // Set up CSS size if it's not set up already
        if (!canvas.style.width)
            canvas.style.width = canvas.width + "px";
        if (!canvas.style.height)
            canvas.style.height = canvas.height + "px";

        var scaleFactor = dpi / 96;
        canvas.width = Math.ceil(canvas.width * scaleFactor);
        canvas.height = Math.ceil(canvas.height * scaleFactor);
        var ctx = canvas.getContext("2d");
        ctx.scale(scaleFactor, scaleFactor);
    }

    var exportPNGElement = document.getElementById("export-png");
    if ("download" in exportPNGElement) {
        exportPNGElement.addEventListener("click", function(e) {
            map.once("postcompose", function(event) {
                var canvas = event.context.canvas;
                setDPI(canvas, 300);
                exportPNGElement.href = canvas.toDataURL("image/png");
            });
            map.renderSync();
            //alert(en + " image created");
        }, false);
    }

But the script fails with the setDPI function being called - works fine without. Even setting the canvas width explicitly does not make a difference:

                var canvas = event.context.canvas;
                canvas.width=1024;
                exportPNGElement.href = canvas.toDataURL("image/png");

I can increase the map image size in css but the toDataURL call seems to fall over at higher resolutions - 1000 x 1000 for example.

How can I change or set the canvas size so that I can get higher resolution output to PNG?

Community
  • 1
  • 1
James Bourne
  • 123
  • 3
  • 9

1 Answers1

1

You need to call the function in the precompose-event, i think.

    map.once('precompose', function(event) {
       setDPI('mycanvas',150);
    });

and then the postcompose with ...toDataURL('image/png');...

The solution mentioned in the other thread is targeting the viewed canvas where its "DOM-size" is downscaled by the css-container wrapping it (CSS size). The result on exporting it: is a bigger image where vector sources looks usable.

Raster sources does not show increased "details" when they're not highdpi. They just look blurry/pixeled. But it works for me - more or less. I removed the if-parts out of the setDPI()-function.

If you want to have a better result (on raster-images) you need to set the css-viewport up and then (when the raster-tiles are loaded) you can export the image (still just a bigger image in the end). After that you can set the viewport back.

MichaelJS
  • 193
  • 1
  • 1
  • 10