Screenshoting MapBox using html2canvas creates a black jpg
Asked Answered
G

3

9

I managed to save on my hard drive a screenshot of a map generated with the Google Maps API using html2canvas. I now try to do the same thing with the MapBox API, and all I get on my hard drive is a black screen jpg.

Here is my HTML code :

<!DOCTYPE html>
<html>
    <head>
        <link rel="stylesheet" href="css/main.css">
        <script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.12.2/mapbox-gl.js'></script>
        <script src="js/html2canvas.js"></script>
    </head>

    <body onload="initialize()">
        <div id="map"></div>
        <script src="js/coordinates.js"></script>
    </body>
</html>

Using this CSS to display it fullscreen :

html { height: 100%; }
body { height: 100%; margin: 0px; padding: 0px; }
#map_canvas { width: 100%; height: 100%; }

And this JS script to create the map and take the screenshot :

mapboxgl.accessToken = 'pk.eyJ1IjoiZ2luZ2FsYWJ2IiwiYSI6ImNpaWluNXIzbDAwMjB3ZG02c2hmNGhhMnUifQ.5SC9qnrK7eEdAtwv5Z0S_Q';

var latitude = 48.858565;
var longitude = 2.347198;

function initialize()
{
    var map = new mapboxgl.Map(
    {
        container: 'map',
        style: 'mapbox://styles/mapbox/dark-v8',
        center: [2.347198, 48.858565],
        zoom: 16,
        pitch: 35
    });

    setTimeout(screenshot, 1000);
}

function screenshot()
{
    html2canvas(document.body,
    {
        useCORS: true,
        onrendered: function(canvas)
        {
            var image = document.createElement('a');
            image.href = canvas.toDataURL("image/jpeg").replace("image/jpeg", "image/octet-stream");
            image.download = 'map.jpg';
            image.click();
        }
    });
}

I use a one second timeout to be sure that the map is well created before taking the screenshot. To be sure it was the case, I even created a button in my DOM calling the screenshot() function when clicked, so I am sure that rendering time is not a problem.

I have read here : Print Mapbox/Leaflet Map that html2canvas could not correctly print the map because of some kind of fixed layouts. I wonder why it used to work with Google Maps maps, but never mind. Do you have any idea about that ?

Gatefold answered 23/12, 2015 at 17:15 Comment(0)
P
4

Mapbox has a built in screenshot api:

https://www.mapbox.com/mapbox.js/example/v1.0.0/leaflet-image/

or Grab the canvas data to image via for mapboxgl, you'll need to set preserveDrawingBuffer option for this to work which is off by default... see https://www.mapbox.com/mapbox-gl-js/api/#Map

 var img = new Image();
 var mapCanvas = document.querySelector('.mapboxgl-canvas');
 img.src = mapCanvas.toDataURL();
 window.document.body.appendChild(img);
Panamerican answered 24/12, 2015 at 19:31 Comment(2)
Thank you, but this screenshot api does not work with the mapbox-gl api. It is usefull with traditional mapbox maps though.Gatefold
Hum... Since its webgl / canvas we're talking about i bet you could grab the image data from that. see my edit for le codePanamerican
T
8

Make sure that preservedrawingbuffer is set to true in your map initialization

var map = new mapboxgl.Map({
    container: 'map', // container id
    style: 'mapbox://styles/mapbox/streets-v10', //hosted style id
    center: [-98.5795, 39.8282], // starting position
    zoom: 8, // starting zoom,
    preserveDrawingBuffer: true
});

I used html2canvas and this function

$(function() { 
  $("#btnSave").click(function() { 
      html2canvas(document.body, {
          onrendered: function(canvas) {
              return Canvas2Image.saveAsPNG(canvas);
          }
      });
  })
});
Tizes answered 30/11, 2016 at 16:22 Comment(0)
P
4

Mapbox has a built in screenshot api:

https://www.mapbox.com/mapbox.js/example/v1.0.0/leaflet-image/

or Grab the canvas data to image via for mapboxgl, you'll need to set preserveDrawingBuffer option for this to work which is off by default... see https://www.mapbox.com/mapbox-gl-js/api/#Map

 var img = new Image();
 var mapCanvas = document.querySelector('.mapboxgl-canvas');
 img.src = mapCanvas.toDataURL();
 window.document.body.appendChild(img);
Panamerican answered 24/12, 2015 at 19:31 Comment(2)
Thank you, but this screenshot api does not work with the mapbox-gl api. It is usefull with traditional mapbox maps though.Gatefold
Hum... Since its webgl / canvas we're talking about i bet you could grab the image data from that. see my edit for le codePanamerican
C
1

I'm using version 3.2.0 and nothing was working for me, until I saw this:

https://github.com/mapbox/mapbox-gl-js/issues/2766#issuecomment-370758650

I'm duplicating the code below for quick reference:

function takeScreenshot(map) {
  return new Promise(function(resolve, reject) {
    map.once("render", function() {
      resolve(map.getCanvas().toDataURL());
    });
    /* trigger render */
    map.setBearing(map.getBearing());
  })
}
/* example */
takeScreenshot(map).then(function(data){
  console.log(data);
});

The code works even with preserveDrawingBuffer set to false.

Crackle answered 12/4 at 3:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.