ArcGIS Maps SDK for JavaScript

Capacity Analysis: a custom web mapping solution for understanding the impact of social distancing

In mid April, Esri released Capacity Analysis, a new ArcGIS Online configurable app template to help organizations visualize how interventions to the spread of coronavirus disease 2019 (COVID-19), such as social distancing policies, help flatten the curve and reduce the burden on our healthcare systems.

The Capacity Analysis app allows you to compare the results of two outputs of the CHIME model to observe how well social distancing policies help improve stress on hospitals during the COVID-19 pandemic.
The Capacity Analysis app allows you to compare the results of two outputs of the CHIME model to observe how well social distancing policies help improve stress on hospitals during the COVID-19 pandemic.

In an era where geospatial professionals have access to dozens of configurable apps and one-size-fits-all software with seemingly endless out-of-the-box tools, the Capacity Analysis app is just one example of why custom web app solutions and templates are valuable solutions in helping users explore data.

The need for custom apps

Building custom web apps as opposed to using more generic tools has three main benefits for the end user: focus, simplicity, and full control over UX/UI.

Focus. While the ArcGIS Online map viewer and ArcGIS Pro provide seemingly limitless tools for analyzing, exploring, and visualizing data, they don’t have the same level of focus as a custom app. Focus provides clarity to the end user, reduces the need for extensive documentation, and improves overall understanding of the story behind the app.

Simplicity. This is closely related to focus. The ArcGIS Online map viewer already provides many tools for exploring your data. These include filters, dozens of styling options, and analysis tools. While having multiple options gives you greater flexibility, exploring with only one of these methods is often more effective than others. Going simple and providing access to only the best tool for exploring a particular attribute in a dataset keeps things simple for the user.

Full control. Perhaps the biggest benefit of building a custom solution rather than using out-of-the-box tools, is the developer has full control over the user experience and UI.

The benefits of a template app

Template apps provide all the same benefits as custom web apps with the added benefit of being scaleable so you can reuse the same focused, simplified UI for similar use cases. They can also be reused by others with similar needs. That’s why Capacity Analysis was converted to an app template. It can be used by any local, county, state government, or health organization to understand their ability to meet the demand for COVID-19 patients.

You can read more about getting started with configurable app templates here.

App overview

The remainder of this post will show how Capacity Analysis was designed and built following the principles just mentioned.

The focus

Capacity Analysis was specifically designed to help experts understand and communicate how variances in social distancing policies and variances in compliance to those policies reduce the strain on hospital capacity on a day-by-day basis in the event of a pandemic like COVID-19. This data could be on the state, county, or hospital level.

The layers used in this app are generated from ArcGIS Pro’s COVID-19 Modeling Toolbox, based on Penn Medicine’s CHIME (COVID-19 Hospital Impact Model for Epidemics) and the Centers for Disease Control and Prevention’s (CDC) COVID-19Surge.

Users can use the Capacity Analysis app to compare the differences between various outputs from these models. Read the following blogs for step-by-step introductions to learn how you can use these tools to explore your own data using the Capacity Analysis configurable app.

Sure, you can explore your data in a dashboard with maps showing change over time, or in the ArcGIS Online map viewer. But those tools lack the focus a simplified app could provide.

Capacity Analysis focuses on only one aspect of the COVID-19 pandemic: How does compliance to social distancing policies lessen the burden of our healthcare systems by geography?
Capacity Analysis focuses on only one aspect of the COVID-19 pandemic: How does compliance to social distancing policies lessen the burden of our healthcare systems by geography?

A simple user experience

The following chart from the CDC communicates in a powerful way how timely intervention can reduce hospital stress during a pandemic. It’s simple and effective because it shows two vastly different outcomes in a single view.

Conceptual diagram of flattening the curve. Source: CDC.
Figure 1: Conceptual diagram of flattening the curve. Source: CDC.

We wanted to make the Capacity Analysis app similar in simplicity by allowing users to spatially explore how demand for hospital beds, ICU beds, and ventilators reduces when social distancing policies are followed.

This is effectively done with a simple UI that gives the user two basic controls: a dropdown menu for selecting a variable to explore, and a slider to observe how the demand for the selected variable changes over time.

When the user selects a new variable or moves the slider, the visualization updates, communicating whether current hospital capacity numbers would be able to handle demand given a later peak date.

Full control over functions and layout

After exploring various ways of comparing and contrasting the output data, we decided it was most effective to display the familiar line chart of overall hospital demand over time below two side-by-side maps of two separate model outputs. Each view has a colored border matching the corresponding line in the chart.

Capacity Analysis app preview showing side-by-side maps of different hospital bed demands given different levels of compliance to social distancing recommendations.
Capacity Analysis displays the output of two separate runs of the CHIME model in side-by-side views. This is not possible in the more generic Web Map Viewer.

This makes it easy to compare two different scenarios. For example, the map on the left (orange line on the chart) shows how many ICU beds would be required on June 11 in Florida (this is test data) if 29% of the population follows social distancing recommendations. The map on the right (blue line in the chart) shows the required ICU beds by geography if 55% of the population observed social distancing.

Changing the selected variable or the slider value simultaneously updates the renderer of both layers and the chart to indicate the projected demand for the selected variable on the given date.

Having this level of interactivity synced between a chart and two views is not available in ArcGIS Online. So a custom app was the only solution that could achieve this.

Data Exploration through visualization

In web mapping, data exploration takes the form of querying statistics, displaying popups, changing filters, extents, or updating the renderer of the layer.

The primary method of exploring data in the Capacity Analysis app is updating the renderer using a slider. Each time the slider value updates, the renderer changes.

Capacity Analysis app preview showing side-by-side maps of different hospital bed demands given different levels of compliance to social distancing recommendations.

The symbology is straightforward. A continuous color ramp is used to color each feature based on the percent capacity the hospital is expected to be operating at on a given day. Gray means all is good; the hospitals are operating below capacity. Orange means hospitals have reached 100% capacity. Red indicates hospitals are stressed to 200% capacity or higher.

The size of the symbol indicates the order of magnitude a feature’s hospitals are over capacity. Therefore, the size communicates the total number of patients expected to demand treatment in a hospital and potentially not have access to a hospital bed.

Capacity Analysis app preview showing side-by-side maps of different hospital bed demands given different levels of compliance to social distancing recommendations.
In the test model above, the data for May 29 shows all Florida county hospitals will exceed capacity if social distancing is observed by only 29 percent of the population. The view on the right shows if 55 percent of the population comply with social distancing recommendations, then overall hospitalizations will be well below capacity on the same date. However, some counties, such as Miami-Dade County will still be well above capacity.

Invite interactivity with fast performance

As you move the slider and view the icons change color and size, it may appear the app is updating the visual properties of a renderer. In reality, the renderer’s color and size visual variable properties are static. Having a constant reference for color and size is important when comparing two similar datasets, especially when they involve change over time.

Both layers have the exact same renderer applied. That makes it easy for the user to observe differences between each layer.

The legend of the Capacity Analysis app.
The legend in the Capacity Analysis app representing a test layer of Florida counties. The color and size ranges are always the same, no matter the position of the slider. This makes it easy for the user to understand where change is occurring over time.

Each time the slider updates, the underlying data attribute changes. Rather than store daily values for each attribute as a separate row in the layer, the ArcGIS Pro CHIME tool outputs the projected values for each day as a list of pipe-separated values — one value for each day. This ensures all the data is attached to one geometry and we don’t have duplicate points representing the same geographies.

Pipe separated values of the data generated from the CHIME model.

Each position (or index) of the list indicates the number of days since the start of the model. For example, the sixth value in the web_chosp field is the number of hospital beds expected to be used by COVID-19 patients on the sixth day from the start of the model’s output.

The app uses Arcade expressions to parse the appropriate value from the selected attribute for the given slider position.

const getPercentCapacityExpression = function ({
}) {

  // web_chosp - Projected number of hospital patients
  // web_cicu - Projected number of ICU patients
  // web_cvent - Projected number of ventilators required
  const countsField = analysisParameters.variableFields[variable].COUNTS;

  // oc_hos_num - Total number of available hospital beds
  // oc_icu_num - Total number of available ICU beds
  // oc_vnt_num - Total number of available ventilators
  const capacityField = analysisParameters.variableFields[variable].CAPACITY;

  return `
    var hospitalized = Max(0,Number(Split($feature.${countsField},'|')[${day}]));
    var capacity = IIF($feature.${capacityField} < 1, 1, $feature.${capacityField});
    return (hospitalized / capacity ) * 100;

Each time the user moves the slider handle, the app updates the renderer with the new Arcade expression based on the slider thumb position.

layer.renderer = {
  type: "simple",
  symbol: {
    type: "simple-marker",
    outline: {
      width: 0.5,
      color: [200, 200, 200, 0.5]
  visualVariables: [{
    type: "color",
    valueExpression: getPercentCapacityExpression({
      // hospital beds, ICU beds, ventilators
      // slider position
    valueExpressionTitle: "Hospital Stress",
    stops: [{
      value: 0,
      color: "#bababa",
      label: "under capacity"
    }, {
      value: 100,
      color: "#f4a582",
      label: "100% capacity"
    }, {
      value: 200,
      color: "#ca0020",
      label: "> 200% capacity"
  }, {
    type: "size",
    valueExpressionTitle: "Number of patients above capacity",
    valueExpression: getOveragesExpression({
      // hospital beds, ICU beds, ventilators
      // slider position
    minSize: 2,
    maxSize: 32,
    minDataValue: 1,
    maxDataValue: 2050

This method of using separated values in a single field is very similar to having a client-side table join. Having all the data in one attribute allows the GPU to only process the geometries once, making the app more performant. You can then update a reference to the new data value for each slider change without discarding and re-rendering geometries.

This method allows the renderer in both layers to update at up to 60 frames per second without the eye sore of flashing because all the data already exists on the GPU. Since the geometry is already rendered, the color and size of the icons just need to update based on the data value parsed from the Arcade expression.

The Mapping large datasets on the web blog and Update a renderer’s attribute JS API sample go into more detail about this method of data visualization.


Because of its usefulness to governments and hospital administrators in assessing policy effectiveness, the Capacity Analysis app was converted to a configurable app template so it can be used by others to explore two outputs from the ArcGIS Pro COVID-19 Modeling Toolbox for geographies relevant to them.

Capacity Analysis is an example of why you should always consider using templates or building custom web applications in a focused, simplified manner for data exploration and client-side analytics, even in highly volatile emergency situations like a pandemic.


Check out the following resources for more information about the CHIME model and how to create focused interactive apps.

App development resources

CHIME and COVID-19 resources

About the author

Kristian is a Principal Product Engineer at Esri specializing in data visualization. He works on the ArcGIS Maps SDK for JavaScript, ArcGIS Arcade, and Map Viewer in ArcGIS Online. His goal is to help developers be successful, efficient, and confident in building web applications with the JavaScript Maps SDK, especially when it comes to visualizing data. Prior to joining Esri, he worked as a GIS Specialist for an environmental consulting company. He enjoys cartography, GIS analysis, and building GIS applications for genealogy.

Notify of
Inline Feedbacks
View all comments

Next Article

Mix and match buffer styles for your business solutions

Read this article