mpetroff / print-maps

High-resolution maps in the browser, for printing
https://printmaps.mpetroff.net/
MIT License
286 stars 51 forks source link

Question on using for Leaflet #17

Closed hjrobinson closed 5 years ago

hjrobinson commented 5 years ago

I know there's probably not an easy answer, but I thought I would ask anyway. Is there a way to use this tool for leaflet instead of mapbox-gl?

I have no trouble bringing the map into the panel-body map-container. I have issues when I try to export the map to png or pdf in the createPrintMap function. Here's what I got so far:

function createPrintMap(width, height, dpi, format, unit, zoom, center){
    // bearing, style, pitch) { //Remove bearing,style, and pitch for leaflet;

    // Calculate pixel ratio
    var actualPixelRatio = window.devicePixelRatio;
    Object.defineProperty(window, 'devicePixelRatio', {
        get: function() {return dpi / 96}
    });

    // Create map container
    var hidden = document.createElement('div');
    hidden.className = 'hidden-map';
    document.body.appendChild(hidden);
    var container = document.createElement('div');
    container.style.width = toPixels(width);
    container.style.height = toPixels(height);
    hidden.appendChild(container);
    container.id = 'myContainer'

    var renderMap = L.map(container,{preferCanvas:true}).setView([51.505, -0.09], 13);
    L.tileLayer('https://a.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(renderMap);

    // Render map
    // var renderMap = new mapboxgl.Map({
    //     container: container,
    //     // center: center,
    //     // zoom: zoom,
    //     // style: style,
    //     // bearing: bearing,
    //     // pitch: pitch,
    //     // interactive: false,
    //     // attributionControl: false
    // });
    setTimeout(function(){
        html2canvas(document.getElementById('myContainer'), {
        allowTaint:false,
        useCORS: true,
    }).then(canvas => {
        canvas.toBlob((blob) => {
            saveAs(blob, "my-map.png");
        });
    });
}, 3000);

The png downloads but only shows the very bottom of the map at the top of the screen. If I shrink the browser screen to 25% I get a complete (but shrunken) image. I know this tool was made for mapbox-gl but I thought I would ask anyway to see if you had approached this challenge with Leaflet in the past. I know this is a question and not an issue. Thanks for your time.

mpetroff commented 5 years ago

I fail to see what using Leaflet would accomplish. Leaflet uses pre-rendered raster tiles, so the resolution isn't configurable, defeating the purpose of this tool (I never considered Leaflet when creating this tool because of this). If you just want to save the view, a quick search shows that there are existing tools for doing so.

hjrobinson commented 5 years ago

Your tool offers other advantages, the first is it allows the user to customize the size of the map. I got that part going. The other is it seems to use a hidden element to render the map. That's the part I'm trying to figure out.

If I could configure the dpi it still it would be nice even if as you say there would be zero impact on a rasterized image. There's a discussion on how to use html2canvas to increase the dpi of an image at: https://github.com/niklasvh/html2canvas/issues/241 and a branch of html2canvas here: https://github.com/eKoopmans/html2canvas/tree/develop/dist (which I have not tested) that's supposed to provide a dpi option.

The other Leaflet print/image plugins have issues with Internet Explorer, which is why I'm using html2canvas. As you know Leaflet doesn't have the getCanvas() method that the Mapbox GL JS api does.

All that aside I'm trying to figure out how to download a png and a pdf from a hidden element in a similar manner to your tool except using Leaflet.

mpetroff commented 5 years ago

While I've used Leaflet before, I've never used it for anything like this, so I unfortunately can't be of much help.

Leaflet also doesn't use canvas, which makes capturing its view from a hidden element a considerably different problem than saving the contents of an off-screen canvas as is done here, despite being conceptually similar.

hjrobinson commented 5 years ago

Well, thanks for the input anyway. I think I'm making some progress on it now. Perhaps, if I get it done I'll post a fiddle. I'm still playing with it, but I'm going to try to fake it by adding another hidden div which will contain a second map object, unhide it, add it to the canvas, generate the png and pdf, then rehide it. If it happens fast enough the user won't be aware of the second div. Feel free to close the issue if you have no more comments. Thanks again.