<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<title>Shadow cast | Sample | ArcGIS Maps SDK for JavaScript</title>
<link rel="stylesheet" href="https://js.arcgis.com/5.0/esri/themes/light/main.css" />
<!-- Load the ArcGIS Maps SDK for JavaScript from CDN -->
<script type="module" src="https://js.arcgis.com/5.0/"></script>
const [WebScene, SceneView, ShadowCast] = await $arcgis.import([
"@arcgis/core/WebScene.js",
"@arcgis/core/views/SceneView.js",
"@arcgis/core/widgets/ShadowCast.js",
const view = new SceneView({
id: "f2220db76c6448b4be8083d19ef4cf8d",
directShadowsEnabled: false,
const widget = new ShadowCast({
view.ui.add(widget, "top-right");
// Create the analysis for a certain date.
widget.viewModel.date = new Date("March 1, 2026");
// Customize the threshold analysis that is shown when the app is loaded.
widget.viewModel.thresholdOptions = {
// Areas in the shadow for more than 3 hours are colored transparent red.
// Discreet shadow context is shown in dark gray.
color: [30, 30, 30, 0.7],
view.map.allLayers.forEach((layer) => {
if (layer.title === "Development Scenario A") {
if (layer.title === "Development Scenario B") {
const buttonA = document.getElementById("scenarioA");
const buttonB = document.getElementById("scenarioB");
buttonA.addEventListener("click", (event) => {
buttonB.addEventListener("click", (event) => {
function toggleScenarios(active) {
scenarioA.visible = active === "B" ? false : true;
scenarioB.visible = active === "B" ? true : false;
buttonA.appearance = "outline-fill";
buttonB.appearance = "solid";
buttonA.appearance = "solid";
buttonB.appearance = "outline-fill";
<calcite-button id="scenarioA" appearance="solid">Scenario A</calcite-button>
<calcite-button id="scenarioB" appearance="outline-fill">Scenario B</calcite-button>