<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<title>Take a screenshot of a Scene | Sample | ArcGIS Maps SDK for JavaScript</title>
<!-- Load the ArcGIS Maps SDK for JavaScript from CDN -->
<script type="module" src="https://js.arcgis.com/5.0/"></script>
background-color: rgba(255, 255, 255, 0.8);
border: 10px solid white;
box-shadow: 2px 2px 5px 0 rgba(0, 0, 0, 0.5);
background: rgba(255, 51, 0, 0.1);
border: 2px dashed rgb(255, 51, 0);
<arcgis-scene item-id="c194a3e51a9d48f0b24052efe559ac1a">
<calcite-button id="screenshotBtn" slot="top-left">Select screenshot area</calcite-button>
<div id="screenshotDiv" class="hide">
<img id="screenshotImage" />
<label>Set a text to be displayed on the image: </label
><input type="text" placeholder="Image text" id="textInput" autofocus />
<calcite-button id="downloadBtn" title="Download image"> Download image </calcite-button>
<calcite-button id="closeBtn" title="Back to webscene"> Back to webscene </calcite-button>
<div id="maskDiv" class="hide"></div>
/**********************************************
* Component and view setup
*********************************************/
const viewElement = document.querySelector("arcgis-scene");
await viewElement.viewOnReady();
const screenshotBtn = document.getElementById("screenshotBtn");
// the orange mask used to select the area
const maskDiv = document.getElementById("maskDiv");
// element where we display the print preview
const screenshotDiv = document.getElementById("screenshotDiv");
// the button that triggers download
const downloadBtn = document.getElementById("downloadBtn");
// the button to hide the print preview html element
const closeBtn = document.getElementById("closeBtn");
// add an event listener to trigger the area selection mode
screenshotBtn.addEventListener("click", () => {
screenshotBtn.classList.add("active");
viewElement.classList.add("screenshotCursor");
// define drag event listener
const dragEventListener = (event) => {
// prevent navigation in the view
event.detail.stopPropagation();
// when the user starts dragging or is dragging
if (event.detail.action !== "end") {
// calculate the extent of the area selected by dragging the cursor
Math.min(event.detail.origin.x, event.detail.x),
Math.max(event.detail.origin.x, event.detail.x),
Math.min(event.detail.origin.y, event.detail.y),
Math.max(event.detail.origin.y, event.detail.y),
// set the position of the div element that marks the selected area
// when the user stops dragging
// Remove the listener using the same function reference.
viewElement.removeEventListener("arcgisViewDrag", dragEventListener);
// the screenshot of the selected area is taken
viewElement.takeScreenshot({ area: area, format: "png" }).then((screenshot) => {
// display a preview of the image
// create the image for download
downloadBtn.onclick = () => {
const text = document.getElementById("textInput").value;
// if a text exists, then add it to the image
const dataUrl = getImageWithText(screenshot, text);
downloadImage(`${viewElement.map.portalItem.title}.png`, dataUrl);
// otherwise download only the webscene screenshot
downloadImage(`${viewElement.map.portalItem.title}.png`, screenshot.dataUrl);
// the screenshot mode is disabled
screenshotBtn.classList.remove("active");
viewElement.classList.remove("screenshotCursor");
// Add the listener using the named function reference.
viewElement.addEventListener("arcgisViewDrag", dragEventListener);
function setMaskPosition(area) {
maskDiv.classList.remove("hide");
maskDiv.style.left = `${area.x}px`;
maskDiv.style.top = `${area.y}px`;
maskDiv.style.width = `${area.width}px`;
maskDiv.style.height = `${area.height}px`;
maskDiv.classList.add("hide");
function clamp(value, from, to) {
return value < from ? from : value > to ? to : value;
// creates an image that will be appended to the DOM
// so that users can have a preview of what they will download
function showPreview(screenshot) {
screenshotDiv.classList.remove("hide");
// add the screenshot dataUrl as the src of an image element
const screenshotImage = document.getElementById("screenshotImage");
screenshotImage.width = screenshot.data.width;
screenshotImage.height = screenshot.data.height;
screenshotImage.src = screenshot.dataUrl;
// returns a new image created by adding a custom text to the webscene image
function getImageWithText(screenshot, text) {
const imageData = screenshot.data;
// to add the text to the screenshot we create a new canvas element
const canvas = document.createElement("canvas");
const context = canvas.getContext("2d");
canvas.height = imageData.height;
canvas.width = imageData.width;
// add the screenshot data to the canvas
context.putImageData(imageData, 0, 0);
context.font = "20px Arial";
context.fillStyle = "#000";
context.fillRect(0, imageData.height - 40, context.measureText(text).width + 20, 30);
// add the text from the textInput element
context.fillStyle = "#fff";
context.fillText(text, 10, imageData.height - 20);
return canvas.toDataURL();
function downloadImage(filename, dataUrl) {
const element = document.createElement("a");
element.setAttribute("href", dataUrl);
element.setAttribute("download", filename);
element.style.display = "none";
document.body.appendChild(element);
document.body.removeChild(element);
// hide the print preview html element on click
closeBtn.addEventListener("click", () => {
screenshotDiv.classList.add("hide");