2

I am using Leaflet and Leaflet data visualization framework to draw maps and charts on top of them.

Now I am trying to save map with charts to PNG image, but can successfully export only one layer - maps or charts.

Probably this is because charts in .leaflet-overlay-pane is drawn in SVG element, but map in .leaflet-tile-pane is drawn using DIV/IMG elements.

Found related issues:
1) leaflet+canvg+html2canvas = MyImage.png
2) export to image leaflet map with SVG markers in javascript

How to deal with that? Is there any way to "flatten" SVG and DIV/IMG/Canvas elements to export as image? Or there should be another approach?

Thanks!

Community
  • 1
  • 1
Orbitum
  • 1,585
  • 5
  • 27
  • 47

2 Answers2

1

Use the dom-to-image library

You can use the dom to image library to convert leaflet to a png image.

See the below example:

var mymap = L.map('my-node').setView([51.505, -0.09], 13);

L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', {
        maxZoom: 18,
        attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, ' +
            '<a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, ' +
            'Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
        id: 'mapbox/streets-v11'
    }).addTo(mymap);

var node = document.getElementById('my-node');
var btn = document.getElementById('foo');

// node.innerHTML = "I'm an image now."

btn.onclick = function() {

  domtoimage.toBlob(document.getElementById('my-node'))
    .then(function(blob) {
      window.saveAs(blob, 'my-node.png');
    });
}
#my-node {
  height: 180px;
}

.button {
  padding: 4px;
  margin-bottom: 10px;
}
<script src="https://cdn.bootcss.com/FileSaver.js/2014-11-29/FileSaver.min.js"></script>

<script src="https://cdn.bootcss.com/dom-to-image/2.6.0/dom-to-image.min.js"></script>

<link rel="stylesheet" href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css"
   integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ=="
   crossorigin=""/>

 <script src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js"
   integrity="sha512-gZwIG9x3wUXg2hdXF6+rVkLF/0Vi9U8D2Ntg4Ga5I5BZpVkVxlJWbSQtXPSiUTtC0TjtGOmxa1AJPuV0CPthew=="
   crossorigin=""></script>

<button id="foo" class="button">download img</button>

<div id="my-node">
  You will get a image downloaded.
</div>
hitautodestruct
  • 20,081
  • 13
  • 69
  • 93
0

leaflet-image can not rasterize html. I think your best bet is having some server-side script generate screenshots of the page on request and serve them back to the browser.

I've used wkhtmltopdf to convert leaflet maps to PDF, which takes some tuning to get right.

Jieter
  • 4,101
  • 1
  • 19
  • 31
  • Why leaflet-image can't resterize html? I am not using `L_PREFER_CANVAS = true;` and I see in code IMG tags. More, i can remove check for `map._pathRoot` in `leafletImage(map, callback)` function and create image of leaflet/leaflet-dvf, but without leaflet-dvf svg elements (charts). – Orbitum Jun 07 '16 at 09:50
  • Quoting the leaflet-image README.md: "This library does not rasterize HTML because browsers cannot rasterize HTML. Therefore, L.divIcon and other HTML-based features of a map, like zoom controls or legends, are not included in the output, because they are HTML." Leaflet-image only works with L_PREFER_CANVAS = true; or its leaflet-1.0 equivalent – Jieter Jun 07 '16 at 10:18
  • Strange, because I got it to work without `L_PREFER_CANVAS` on `0.7.7`. Now I am trying to make two PNG. One from `leaflet-image` and another from SVG and combine on server. Issue is that this SVG (from `leaflet-dvf`) is different size (larger). – Orbitum Jun 07 '16 at 10:27