Skip to content

This sample demonstrates switching between 2D and 3D using the Map and Scene components from the ArcGIS Maps SDK for JavaScript.

2D ⇄ 3D toggle approaches:

1. Overlapping components (used here)

Place both <arcgis-map> and <arcgis-scene> custom elements in the DOM. Position the components absolutely so they overlap. Use dynamic styling to fade the components in and out of visibility. Copy the active component's viewpoint to the target component so to maintain the same center, scale, and orientation.

  • Pros: styled transition that can be customized; widgets and overlays remain active in each component; the target component is initialized and available immediately.
  • Cons: higher GPU usage because both components are active.
  • Switch logic:
    Use dark colors for code blocksCopy
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    const showAndHide = (elementToShow, elementToHide) => {
      elementToShow.classList.add("visible");
      elementToHide.classList.remove("visible");
    };
    
    const switchView = (button) => {
      const is2D = button.id === "to-3D"; // Check if switching from 2D.
      // Clone the viewpoint from the currently visible view.
      const activeViewpoint = is2D ? mapViewElement.viewpoint.clone() : sceneViewElement.viewpoint.clone();
      // This adjusts for Web Mercator distortion in 2D maps which causes scale to increase with latitude.
      const scaleConversionFactor = Math.cos((activeViewpoint.targetGeometry.latitude * Math.PI) / 180);
    
      button.id = is2D ? "to-2D" : "to-3D";
      button.innerText = is2D ? "2D" : "3D";
    
      if (is2D) {
        // 2D → 3D: Remove distortion by shrinking the scale (zoom in to match true ground distance).
        activeViewpoint.scale *= scaleConversionFactor;
        sceneViewElement.viewpoint = activeViewpoint; // Set target viewpoint to current viewpoint.
        showAndHide(sceneViewElement, mapViewElement);
      } else {
        // 3D → 2D: Add distortion by inflating the scale (zoom out to match perceived 2D zoom).
        activeViewpoint.scale /= scaleConversionFactor;
        mapViewElement.viewpoint = activeViewpoint; // Set target viewpoint to current viewpoint.
        showAndHide(mapViewElement, sceneViewElement);
      }
    };

2. Container reassignment (single host element)

Keep a single div or component host, setting mapView.container = div and sceneView.container = null, and vice versa.

  • Pros: lower memory footprint than the overlapping components approach because only one view renders at a time; fewer WebGL contexts.
  • Cons: widgets and UI elements are torn down and recreated on each switch unless they are manually preserved; no built-in cross-fade effect; a brief visual flash occurs during view initialization; greater code complexity.

Choose the overlapping components approach if preserving UX smoothness and maintaining UI state are priorities. Consider the hidden components approach if GPU usage is a concern. Use container reassignment if resource efficiency on constrained devices matters most.

We use the shared viewpoint to carry over the center, scale, and rotation, and when switching to 3D, we also include the camera properties. In the Web Mercator projection, degree-based coordinates compress east–west ground distances by a factor of cos(latitude). This means that the same scale at higher latitudes covers less actual ground. Applying a cos(latitude) adjustment ensures that the perceived ground distance remains consistent between 2D and 3D views.

Key steps:

  1. Overlap <arcgis-map> and <arcgis-scene> with absolute positioning.
  2. Wait for both components' viewOnReady() promises.
  3. Capture the active view's viewpoint and adjust viewpoint.scale using Math.cos(latitudeRadians).
  4. Assign the modified viewpoint to the target component's viewpoint property.
  5. Toggle a CSS class to fade the outgoing view and reveal the incoming one.

Considerations when switching between 2D and 3D

Keep in mind that switching from a MapView to a SceneView requires careful consideration of several factors. See the list below for some of the key points to review. This list is not comprehensive.

  • Data types - Some layers aren't supported in 2D because of their 3D nature. These include SceneLayer, IntegratedMeshLayer, and PointCloudLayer. They will need to be removed from the map instance altogether, or replaced with 2D counterparts. For example, you could switch a SceneLayer representing buildings with a polygon FeatureLayer representing building footprints. ElevationLayer doesn't need to be considered as closely as the other layers mentioned above since the Map's ground is ignored in MapViews.
  • Symbols - While most 2D symbols are usable in SceneView, all 3D symbols are not supported in MapViews. Renderers may need to be reconfigured if 3D symbols are used.

Your browser is no longer supported. Please upgrade your browser for the best experience. See our browser deprecation post for more details.