javascriptangularesriarcgis-js-apiesri-maps

How to get a screenshot of the ESRI Map - Angular


How to get a screenshot of the Esri map at its current state on the UI and make it as downloaded as Pdf from Angular? The following code is my current .ts code and please let me know if there are additional parts to be added.

esri-map.component.html

<!-- Map Div -->
<div #mapViewNode></div>
 

esri-map.component.ts

// Initialize MapView and return an instance of MapView
    initializeMap(esriToken) {
    const container = this.mapViewEl.nativeElement;
    config.apiKey = esriToken;
    const horizonData: any[] = this.esiriData || [];

//load the webMap
const webmap = new WebMap({
      portalItem: {
        id: this.webMapId
      }
    });

// load the ParcelAtlas feature layer
const layer = new FeatureLayer({
    url: this.featureLayerUrl,
    });
  webmap.add(layer);

const view = new MapView({
  container,
  map: webmap,
  zoom: 4,
  center: [-97.63, 38.34],
});

//legend Icon
const legend = new Legend ({
  view: view
});
const legendExpand = new Expand(
  {
  view,
  content: legend,
  expanded: false,
})
view.ui.add(legendExpand, "top-left");

  const renderer = new SimpleRenderer({
    symbol: new TextSymbol({
      color: "red",
      text: "\ue61d",
      font: {
        size: 30,
        family: "CalciteWebCoreIcons"
    }
    })
  });

  const dataFeedLayer = new FeatureLayer({
  source: horizonData.map((d,i)=>(
  {
      geometry: new Point({
        longitude: d.longitude,
        latitude: d.latitude
      }),
      attributes: {
        ObjectID: i,
        ...d
      }
  }
)),
  objectIdField: 'ObjectID',
  geometryType: "point",
  renderer: renderer,
});

  webmap.add(dataFeedLayer);

  let options = {
    width: 2048,
    height: 2048
  };

  view.takeScreenshot(options).then(function(screenshot) {
    let imageElement = document.getElementById("screenshotImage");
    imageElement.src = screenshot.dataUrl;
  });
  this.view = view;

  return this.view.when();

  }

error: Property 'src' does not exist on type 'HTMLElement'.ts(2339)


Solution

  • The problem that you are having is because you do not have a node for the image, screenshotImage is no on the component.

    I am not sure how you want to show the image, so I will use this example I made for you.

    <html>
    
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no">
        <title>Screenshot Example</title>
        <style>
            html,
            body,
            #viewDiv {
                padding: 0;
                margin: 0;
                height: 100%;
                width: 100%;
            }
            #screenshotDiv {
                position: absolute;
                top: 0;
                right: 0;
                background-color: transparent;
                z-index: 1;
                display: flex;
                flex-direction: column;
            }
            .action-button {
                width: 200px;
                padding: 0.6em;
                border: 1px solid #0079c1;
                text-align: center;
                background-color: white;
                cursor: pointer;
            }
            .action-button:hover,
            .action-button:focus {
                background: #0079c1;
                color: white;
            }
        </style>
    
        <link rel="stylesheet" href="https://js.arcgis.com/4.18/esri/css/main.css">
        <script src="https://js.arcgis.com/4.18/"></script>
    
        <script>
            require([
                "esri/Map",
                "esri/views/MapView"
            ], function (Map, MapView) {
    
                const map = new Map({
                    basemap: "streets-navigation-vector"
                });
    
                const view = new MapView({
                    container: "viewDiv",
                    map: map,
                    zoom: 12,
                    center: {
                        latitude: 32.7353,
                        longitude: -117.1490
                    }
                });
    
                const btn = document.getElementById("screenshotBtn");
                const img = document.getElementById("screenshotImg");
    
                view.when(function() {
                    btn.addEventListener("click", function() {
                        view.takeScreenshot({
                                width: 200,
                                height: 200
                            }).then(function(screenshot) {
                            img.src = screenshot.dataUrl;
                        });
                    });
                });
    
            });
        </script>
    </head>
    
    <body>
        <div id="viewDiv" class="esri-widget">
            <div id="screenshotDiv">
                <button id="screenshotBtn" class="action-button esri-widget">
                    Take Screenshot
                </button>
                <img id="screenshotImg"/>
            </div>
        </div>
    </body>
    
    </html>

    I think this translation to Angular should work,

    esri-map.component.html

    <div #mapViewNode>
        <div class="screenshotDiv">
            <button class="action-button esri-widget" (click)="takeScreenshot()">
                Take Screenshot
            </button>
            <img [src]="screenshotImgSrc"/>
        </div>
    </div>
    

    esri-map.component.ts

    takeScreenshot() {
        const self = this;
        this.view.takeScreenshot({
            width: 200,
            height: 200
        }).then(function(screenshot) {
            self.screenshotImgSrc = screenshot.dataUrl;
        });
    }
    

    takeScreenshot, view, and screenshotImgSrc needs to be properties of the component.