Thematic multivariate visualization (2D)

Note: Support for 3D on mobile devices may vary, view the system requirements for more information.

In this tutorial we will explore visual variables and learn how to use them in multivariate mapping. While the sample showcased here will only use 2D symbols, the same principles apply to using visual variables with 3D symbols. For examples of using visual variables in 3D, see the Symbolize 2D features with 3D symbols sample and the ExtrudeSymbol3DLayer sample.

Prior to completing the following steps, you should be familiar with views, Map, and FeatureLayer. If necessary, complete the following tutorials first:

1. Create a simple map

First create a simple Map and reference it in a View. Add a FeatureLayer to the map using the URL in the snippet below. Your JavaScript may look something like the code below:

require([
  "esri/Map",
  "esri/views/SceneView",
  "esri/layers/FeatureLayer",
  "dojo/domReady!"
], function(
  Map,
  SceneView,
  FeatureLayer
) {

  // Create a feature layer for zip codes in Los Angeles
  var zipLyr = new FeatureLayer({
    url: "https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/Enriched%20USA%20ZIP%20Code%20Areas/FeatureServer/0",
    outFields: ["*"],
    definitionExpression: "NAME='Los Angeles'"
  });

  // Create the map
  var map = new Map({
    basemap: "gray",
    layers: [zipLyr]
  });

  // Create the SceneView
  var view = new SceneView({
    container: "viewDiv",
    map: map,
    zoom: 12,
    center: [-118.302, 34.022]
  });
});

2. Define a color visual variable

There are four types of visual variables: color, size, opacity, and rotation. Each may be used to visualize a numeric variable in the data on a continuous ramp. The minimum and maximum values may be defined, or stops may be used to create class breaks.

In this step, we'll use a ramp of two colors (pale yellow to dark blue) to visualize the percentage of the population in each ZIP code who owns a smart phone.

A visual variable is a simple object that looks like the following:

// Define the variable
var colorVisVar = {
  // The type must be set to color for the renderer to know it will use color
  type: "color",
  // Assign the field name to visualize with color (number of smart phone owners)
  field: "MP27002a_B",
  // If normalizing set the field to normalize by (in this case total population)
  normalizationField: "TOTPOP_CY",
  // Set the color ramp based on two values (min/max) and two colors
  stops: [
      { value: 0.33, color: "#FFFCD4" },
      { value: 0.53, color: "#0D2644" }
  ]
};

Features where the percentage of the population owns a smart phone is between 33% and 53% will be assigned a color relative to the colors assigned the minimum and maximum values.

3. Define a size visual variable

The principles of defining visual variables are the same between color, size, and opacity. In this step, we'll use the size of the marker symbol to visualize the population density of each zip code.

The size object should look like the following:

var sizeVisVar = {
  // The type must be set to size for the renderer to know size will be altered
  type: "size",
  // Assign the field name to visualize with size (total population)
  field: "TOTPOP_CY",
  // Set the field to normalize the values by (in this case square miles)
  normalizationField: "SQMI",
  valueUnit: "unknown",
  // Create a size ramp based on the min/max values
  stops: [
    { value: 4000, size: 6 },
    { value: 23000, size: 40 }
  ]
};

4. Define the renderer and assign the visual variables to it

Once the objects are set, they may be assigned to a renderer. In most cases a SimpleRenderer will suffice.

When constructing the renderer, a default symbol should be assigned to it so the renderer will know how to treat the visual variables. Since ZIP codes are polygons, a SimpleFillSymbol could be used here, but then it couldn't take advantage of the size visual variable since fill symbols don't have size properties associated with them. In this case, we should use a SimpleMarkerSymbol so the renderer can size the markers based on the properties set in the size object.

var renderer = {
  type: "simple",  // autocasts as new SimpleRenderer()
  // Define a default marker symbol.
  symbol: { type: "simple-marker"},  // autocasts as new SimpleMarkerSymbol()
  // Set the color and size visual variables on the renderer
  visualVariables: [colorVisVar, sizeVisVar]
};

5. Set the renderer on the layer

Once the renderer's properties are all set, you can assign it to the layer. In this sample, we want to set the renderer prior to adding the layer to the map.

// Define the renderer
var renderer = {
  type: "simple",  // autocasts as new SimpleRenderer()
  // Define a default marker symbol.
  symbol: { type: "simple-marker"},  // autocasts as new SimpleMarkerSymbol()
  // Set the color and size visual variables on the renderer
  visualVariables: [colorVisVar, sizeVisVar]
};

// Set the renderer on the layer
var zipLyr = new FeatureLayer({
  url: "https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/Enriched%20USA%20ZIP%20Code%20Areas/FeatureServer/0",
  outFields: ["*"],
  definitionExpression: "NAME='Los Angeles'",
  renderer: renderer
});

// Create the Map
var map = new Map({
  basemap: "gray",
  layers: [zipLyr]
});

6. Summary

Visual variables are a simple and powerful way to visualize data. They don't involve complicated classification schemes and give you the option to map multiple variables in the same data set. As a cautionary note, using too many visual variables can make the map confusing and difficult to read.

As noted above, visual variables may be used in 3D symbols. Because of the nature of 3D visualization, multiple size varialbes may be set on a single layer. See the Symbolize 2D features with 3D symbols sample for an example of this.

After following the steps outlined above, you final JavaScript code should look like the following:

  require([
    "esri/Map",
    "esri/views/SceneView",
    "esri/layers/FeatureLayer",
    "dojo/domReady!"
  ], function(Map, SceneView, FeatureLayer
) {
  // URL to the service containing smart phone ownership data
  var url = "https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/Enriched%20USA%20ZIP%20Code%20Areas/FeatureServer/0";

  var colorVisVar = {
    type: "color",
    field: "MP27002a_B",
    normalizationField: "TOTPOP_CY",
    stops: [
      { value: 0.33, color: "#FFFCD4" },
      { value: 0.53, color: "#0D2644" }
    ]
  };

  var sizeVisVar = {
    type: "size",
    field: "TOTPOP_CY",
    normalizationField: "SQMI",
    valueUnit: "unknown",
    stops: [
      { value: 4000, size: 6 },
      { value: 23000, size: 40 }
    ]
  }

  var renderer = {
    type: "simple",  // autocasts as new SimpleRenderer()
    // Define a default marker symbol with a small outline
    symbol: {
      type: "simple-marker",  // autocasts as new SimpleMarkerSymbol()
      outline: { // autocasts as new SimpleLineSymbol()
        color: [128,128,128],
        width: 0.5
      }
    },
    // Set the color and size visual variables on the renderer
    visualVariables: [colorVisVar, sizeVisVar]
  };

  // Set the renderer on the feature layer
  var zipLyr = new FeatureLayer({
    url: url,
    outFields: ["*"],
    definitionExpression: "NAME='Los Angeles'",
    renderer: renderer,
    // This prevents the markers from "billboarding" when the SceneView is tilted
    elevationInfo: {
      mode: "on-the-ground"
    }
  });

  var map = new Map({
    basemap: "gray",
    layers: [zipLyr]
  });

  var view = new SceneView({
    container: "viewDiv",
    map: map,
    zoom: 12,
    center: [-118.302, 34.022]
  });
});

7. Additional visualization tutorials and samples

Sample search results

TitleSample

There were no match results from your search criteria.