Search code examples
mapbox-gl-jsdeck.glreact-map-gl

Export png from deckl map


I'm using react-map-gl with deck.gl to load layers into mapbox.

I'm trying to export a png image of the map with layers but when download the image doesn't show the layers.

The layers are: one GeojsonLayer and one HexagonalLayer.

How can show layers in my png??

<MapGL
  ref={this.mapRef}
  {...viewport}
  className="mapbox"
  mapStyle={mapStyle}
  mapboxApiAccessToken={MAPBOX_TOKEN}
  preserveDrawingBuffer={true}
  attributionControl={false}
  onLoad={this.handleLoad}
  onViewportChange={(viewport) => {
    viewport.width = "100%";
    viewport.height = "400px";
    this.setState({ viewport });
  }}
>
  <DeckGL layers={layers} onHover={this.onHoverDeckgl} viewState={viewport} />
</MapGL>;

// This is my method to download the image.

downloadImage = () => {
    const fileName = `${"Mapa"}_${moment().format(
        "DD_MM_YYYY_ HH_mm"
    )}.png`;

    const canvas = this.state.mapGL.getCanvas();
    canvas.toBlob(blob => {
        FileSaver.saveAs(blob, fileName);
    });
};

Solution

  • Finally, I did it!!!

    I fould a solution to combine canvas from mapbox and canvas from deckgl.

    1. Aadd id to Deckgl Component and ref

      return (
           <DeckGL
              id="deck-gl-canvas"
              ref={this.deckRef}
              layers={layers}
              onHover={this.onHoverDeckgl}
              onLoad={this.handleLoad}
              viewState={viewport}
           >
              {this.renderTooltip()}
           </DeckGL>
      );
      
      // pass deck reference where will be action to download image
      handleLoad = () => {
          const deck = this.deckRef.current.deck;
          this.props.onGetDeckGL(deck);
      };
      
    2. add ref to Mapbox Component and pass will be the action to download image

    3. Call redraw to deck

    4. Combine canvas on a third canvas

      downloadImage = () => {
          const fileName = "Map.png";
      
          const { mapGL, deck } = this.state;
          const mapboxCanvas = mapGL.getCanvas(
              document.querySelector(".mapboxgl-canvas")
          );
          deck.redraw(true);
          const deckglCanvas = document.getElementById("deck-gl-canvas");
      
          let merge = document.createElement("canvas");
          merge.width = mapboxCanvas.width;
          merge.height = mapboxCanvas.height;
      
          var context = merge.getContext("2d");
      
          context.globalAlpha = 1.0;
          context.drawImage(mapboxCanvas, 0, 0);
          context.globalAlpha = 1.0;
          context.drawImage(deckglCanvas, 0, 0);
      
          merge.toBlob(blob => {
              FileSaver.saveAs(blob, fileName);
          });
      };