Skip to main content

Caller-owned 2D/3D switches

map.sqs.viewModeState() asynchronously returns an immutable description: mode, projection, pitch, terrain and pitch-switch conditions. The caller supplies the button UI.

const state = await map.sqs.viewModeState();
if (state.canSwitchTo3d) {
  map.setPitch(state.default3dPitch); // immediate 45 degrees
  await map.sqs.flush({ render: true });
}
// Restore an explicit zero pitch; no hidden previous-pitch restore.
map.setPitch(0);
await map.sqs.flush({ render: true });

Mercator without terrain and at zero pitch is 2d; nonzero pitch or terrain is 3d. Globe is 3d even at zero pitch. Geographic projection does not support pitch. canSwitchTo3d/2d describes projection/terrain camera conditions only: actual layer/resource combinations may reject during candidate validation. A query is not proof of a presented frame.

The default target is 45 degrees, maximumPitch is 65, restorePolicy is explicit-target-pitch and switchMethod is setPitch. Existing setPitch shares camera candidate validation, command acknowledgment and movestart/move/pitchstart/pitch/pitchend/moveend events. flush(render:true) confirms an actual frame. For animation, use easeTo({pitch:45,duration:300}) and existing animation terminal state. Handle failure through flush rejection/error.

setPitch(0) neither disables terrain nor exits globe. Use setTerrain(null) and setProjection({type:'mercator'}) explicitly, following source/projection constraints. Globe or enabled terrain reports canSwitchTo2d=false. Reads emit no change event; refresh after existing camera/terrain/sqs.viewchange notifications.

Raw SDK: view.viewModeState()/view.flush(). Shared scripts: map.sqs.viewModeState()/map.sqs.flush(). The desktop legacy free GIS 3D scene is outside the shared camera and rejects explicitly. Native-library QuickJS and browser main-thread/Worker use the same portable script. Application mobile/device acceptance remains separate.