1

I have integrated a Esri Map in my angular application. In the application there is a download button where user clicks on that download button the screenshot of an Esri Map should taken implicitly and that screenshot should download it as a pdf.

Could you please help me on this?

arcgis-js-api version 4.2.1 angular version 11.

.ts file

 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 feature layer
const layer = new FeatureLayer({
    url: this.featureLayerUrl,
    });
  webmap.add(layer);

const view = new MapView({
  container,
  map: webmap,
});

  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();

  }

.html file

<kendo-pdf-export #pdf paperSize="A4" margin="1cm" [scale]="scale">
<!-- Map Div -->
<div #mapViewNode></div>
 <div class="float-right">
              <div class="downloa-ico pr-1 float-left" (click)="pdf.saveAs('sample.pdf')"></div>
            </div>
</kendo-pdf-export>
Kalana Tebel
  • 135
  • 4
  • 17
  • Hi @KalanaTebel, take a look to this question/answer, it is a similar issue [how-to-get-a-screenshot-of-the-esri-map-angular](https://stackoverflow.com/questions/70151194/how-to-get-a-screenshot-of-the-esri-map-angular/70176206#70176206), let me know if it solve your problem or it is something else – cabesuon Dec 09 '21 at 18:18
  • Hi @cabesuon. Yes up to that level I have completed. My concern is how to take that screenshot implicitly without user manually take the screenshot and then save it as a pdf. not a png or jpg. Thanks – Kalana Tebel Dec 10 '21 at 04:57

1 Answers1

1

Here you have an example of generating a PDF instead of an image with the base code of a past example and the library jsPDF.

The button is just an example on how to dispatch the action (in this case screenshot + pdf generation), it could be anything.

<html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no">
    <title>Screenshot to PDF - 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.20/esri/css/main.css">
    <script>
        const options = {
            dojoConfig: {
                async: true,
                packages: [
                    {
                        location: 'https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.4.0/jspdf.umd.min.js',
                        name: 'jsPDF'
                    }
                ]
            }
        };
    </script>
    <script src="https://js.arcgis.com/4.20/"></script>
    <script>
        require([
            "esri/Map",
            "esri/views/MapView",
            "https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.4.0/jspdf.umd.min.js"
        ], function (Map, MapView, jsPDF) {

            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: 400,
                            height: 400
                        }).then(function(screenshot) {
                            var doc = new jsPDF.jsPDF({
                                orientation: 'p',
                                unit: 'px',
                                format: 'a4'
                            })
                            doc.setFontSize(40)
                            doc.text(35, 25, 'This is your screenshot')
                            doc.addImage(screenshot.dataUrl, 'PNG', 15, 40, 200, 200)
                            doc.save("screenshot.pdf");
                    });
                });
            });

        });
    </script>
</head>

<body>
    <div id="viewDiv" class="esri-widget">
        <div id="screenshotDiv">
            <button id="screenshotBtn" class="action-button esri-widget">
                Take Screenshot
            </button>
        </div>
    </div>
</body>

</html>
cabesuon
  • 4,860
  • 2
  • 15
  • 24
  • Hi! My map is one component and the screenshot button is in another component. So in that case how can I achieve this? – Kalana Tebel Dec 27 '21 at 14:00
  • If the screenshot button component is a child of the map component then it is straightforward, just emit an event to the parent, the map component ([angular docs - output](https://angular.io/guide/inputs-outputs#sending-data-to-a-parent-component)). If it is not a child then, 1) using `output` you will have to bubble up the event to the first common ancestor; and then,2) using `input` you push it down to the map. I am assuming you are using "pure" angular component interaction methods. – cabesuon Dec 28 '21 at 12:19
  • Yeah got it! Thank you so much :) – Kalana Tebel Dec 29 '21 at 05:13
  • Glad it works ! – cabesuon Dec 29 '21 at 13:35