Select to view content in your preferred language

How to get legend symbology from Legend/LegendViewModel to make custom Legend/LayerList combo

668
1
02-07-2024 08:58 AM
Clinton_Lunn
Occasional Contributor

Hi all,

I am attempting to make a combined LayerList and Legend panel inside of a React application. Pulling out the LayerList and adding buttons and sliders for visibility and opacity was pretty straight forward, but I've been stuck on how to pull out the symbology in the legend. 

I'm including a minimal sample where I print out the items to the console but iterating over them doesn't seem to work even though the docs shows methods for a Collection of ActiveInfoLayers that would let me iterate over them. There also seems to be a difference in how the symbology is structured within these objects too. I.e. FeatureLayer symbology is represented by an <svg> element, whereas a MapImageLayer seems to be represented by a base64 string that (I think) would be converted to an image. 

Am I on the correct route for this? Is there a way that I can take a layer/sublayer id and pull out the layer symbology to use elsewhere in my app?

attaching a few screenshots to help show what I mean:

This shows how a MapImageLayer sublayer is available

Clinton_Lunn_0-1707324901716.png

 

This shows how a FeatureLayer symbology is available

Clinton_Lunn_1-1707325000967.png

 

<html lang="en">

<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
  <title>Intro to MapImageLayer | Sample | ArcGIS Maps SDK for JavaScript 4.28</title>

  <link rel="stylesheet" href="https://js.arcgis.com/4.28/esri/themes/light/main.css" />
  <script src="https://js.arcgis.com/4.28/"></script>

  <style>
    html,
    body,
    #viewDiv {
      padding: 0;
      margin: 0;
      height: 100%;
      width: 100%;
    }
  </style>

  <script>
    require(["esri/Map", "esri/views/MapView", "esri/layers/MapImageLayer", "esri/layers/FeatureLayer", "esri/widgets/Legend", "esri/core/reactiveUtils"], (
      Map,
      MapView,
      MapImageLayer,
      FeatureLayer,
      Legend,
      reactiveUtils
    ) => {
      /*****************************************************************
       * Create a MapImageLayer instance pointing to a Map Service
       * containing data about pool permits in Southern California
       *****************************************************************/
      const permitsLayer = new MapImageLayer({
        portalItem: {
          // autocasts as new PortalItem()
          id: "d7892b3c13b44391992ecd42bfa92d01"
        }
      });

      const qFaultsLayer = new MapImageLayer({
        url: 'https://webmaps.geology.utah.gov/arcgis/rest/services/Hazards/quaternary_faults_with_labels/MapServer',
        sublayers: [
          {
            id: 0,
            visible: true,
          },
          {
            id: 1,
            visible: true,
          },
        ],
        title: 'Hazardous (Quaternary age) Faults',
        visible: true,
      });

      const quadBoundariesLayer = new FeatureLayer({
        url: 'https://services.arcgis.com/ZzrwjTRez6FJiOq4/arcgis/rest/services/Utah_Geologic_Hazards_Supplemental_Data_View/FeatureServer/0',
        title: 'USGS 1:24,000-Scale Quadrangle Boundaries',
        visible: true,
      });

      /*****************************************************************
       * Add the layer to a map
       *****************************************************************/
      const map = new Map({
        basemap: "dark-gray-vector",
        layers: [permitsLayer, quadBoundariesLayer, qFaultsLayer]
      });

      const view = new MapView({
        container: "viewDiv",
        map: map
      });

      // add a legend
      const legend = new Legend({
        view: view,
      });

      view.ui.add(legend, "bottom-left");

      // extract legend items from the legend viewmodel
      const legendViewModel = legend.viewModel;
      const activeLayerInfos = legendViewModel.activeLayerInfos;

      // activeLayerInfos.items shows data for the layers in the legend
      console.log(activeLayerInfos.items);

      // shows nothing
      activeLayerInfos.forEach(element => {
        console.log(element);
      })

      // shows nothing
      activeLayerInfos.items.forEach(item => {
        console.log(item);
      })
    });
  </script>
</head>

<body>
  <div id="viewDiv"></div>
</body>

</html>

 

0 Kudos
1 Reply
Sage_Wall
Esri Contributor

Hi @Clinton_Lunn ,

Have you seen this sample application that adds a legend into the layer list? As a heads up we are refactoring the LayerList widget in the next release (4.29) to use calcite components. This might break many of your custom modifications.  If you really want to go down the custom widget route, you might want to take advantage of the renderPreviewHTML method for the symbology 

0 Kudos