基于JavaScript API的场景化Web Scene开发:多场景创建报错求助
核心报错原因
- 未提前获取DOM实例:代码直接使用
buttonA、buttonB绑定点击事件,但没有通过DOM API获取对应按钮元素,会直接抛出未定义引用错误,这是切换第二个场景报错的核心诱因。 - 场景逻辑缺失:当前仅实现了图层可见性切换,没有绑定你需要的分时段光照、时间参数,无法实现不同时段太阳运动影响的展示需求。
- 无空值校验:图层加载完成前点击按钮,
scenarioA/scenarioB为null时调用visible属性会触发报错。
解决实现方案
不需要重复创建WebScene实例,复用现有视图仅切换配置即可,优化后的核心逻辑如下:
- 先获取按钮DOM实例再绑定事件
- 预先定义每个场景对应的时间、光照等配置参数
- 切换场景时同步更新图层可见性、时间、光照参数
- 所有操作前增加非空校验,避免空值报错
完整可运行代码
<html> <head> <meta charset="utf-8" /> <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" /> <link rel="stylesheet" href="https://js.arcgis.com/4.21/esri/themes/light/main.css" /> <script src="https://js.arcgis.com/4.21/"></script> <style> html, body, #viewDiv { padding: 0; margin: 0; height: 100%; width: 100%; } #selection { position: absolute; bottom: 20px; left: 20px; right: 20px; display: flex; justify-content: center; } .esri-button { max-width: 300px; margin-left: 5px; } .esri-button--secondary { background-color: white; } </style> <script> require([ "esri/WebScene", "esri/views/SceneView", "esri/widgets/ShadowCast" ], function (WebScene, SceneView, ShadowCast) { // 提前获取DOM元素 const buttonA = document.getElementById('scenarioA') const buttonB = document.getElementById('scenarioB') const view = new SceneView({ container: "viewDiv", map: new WebScene({ portalItem: { id: "f2220db76c6448b4be8083d19ef4cf8d" } }), qualityProfile: "high", environment: { lighting: { directShadowsEnabled: true } } }); const widget = new ShadowCast({ view }); view.ui.add(widget, "top-right"); // 预定义不同场景的配置:时间、阴影开关等,可按需扩展 const scenarioConfig = { A: { time: new Date("May 1, 2021 09:00:00"), shadowEnabled: true }, B: { time: new Date("May 1, 2021 15:00:00"), shadowEnabled: true } } let scenarioA = null; let scenarioB = null; view.when(() => { view.map.allLayers.forEach((layer) => { if (layer.title === "Development Scenario A") { scenarioA = layer; } if (layer.title === "Development Scenario B") { scenarioB = layer; } }); // 初始化默认显示场景A toggleScenarios("A") }); buttonA.addEventListener("click", (event) => { toggleScenarios("A"); }); buttonB.addEventListener("click", (event) => { toggleScenarios("B"); }); function toggleScenarios(active) { // 非空校验,避免图层未加载完成时报错 if(!scenarioA || !scenarioB) return // 切换图层可见性 scenarioA.visible = active === "A"; scenarioB.visible = active === "B"; // 切换场景对应的时间和光照配置 widget.viewModel.date = scenarioConfig[active].time; view.environment.lighting.directShadowsEnabled = scenarioConfig[active].shadowEnabled; // 切换按钮样式 if (active === "B") { buttonA.classList.add("esri-button--secondary"); buttonB.classList.remove("esri-button--secondary"); } else { buttonA.classList.remove("esri-button--secondary"); buttonB.classList.add("esri-button--secondary"); } } }); </script> </head> <body> <div id="viewDiv"> <div id="selection"> <button id="scenarioA" class="esri-button">Scenario A</button> <button id="scenarioB" class="esri-button esri-button--secondary"> Scenario B </button> </div> </div> </body> </html>
内容的提问来源于stack exchange,提问作者user17147370
相关产品推荐
相关产品推荐

