Maps are a great tool for showcasing where something occurred, but it is often a challenge for digital cartographers to highlight when something occurred and the temporal tends surrounding it. While the Map Viewer in ArcGIS Online supports dynamic charts, I was looking for different ways to graphically present this information using the new Arcade content block options.
Ideally, I wanted an Arcade expression that would iterate through my temporal data, and generate a color-coded table for each year, as seen above. I also wanted the code to work for any dataset, without having to make significant modifications.
The full resulting Arcade expression is at the bottom of the article (along with a shout-out for the Product Engineer who inspired this), but let me walk you through what is happening and how to make this work in your own map.
We start with the data. In my example, I'm using some temporal data from CDC on Lyme Disease incidence rates from 2010-2019. The schema is simple to work with:
Name | Population | F2010 | F2011 | F2012... |
Maine | 1328361 | 42.10 | 60.30 | 66.60 |
Once this layer is added to Map Viewer, we select the layer from the table of contents and select the + Add content option. Here we see a new option for Arcade. Now is where the fun begins.
The script is written for users to give four inputs:
Depending on the classification of your colors, you can add and remove lines from these functions, as necessary.
But that is it! The Arcade script handles the rest. It will count the number of categories and design a table divided into equally spaced sections. Then it applies the labels at the bottom of the table.
The result is a bar that is data-driven and can be surrounded by other blocks in the popup, like text, charts, and tables.
It can even be added as a piece within other HTML content:
Here is the full expression for you to modify:
(Note: This expression was updated on 31 DEC 2021)
// Define the years of the timeline.
// The script will iterate through this array
var yearsArray = ["2010", "2011", "2012", "2013"];
// Define the matching fields containing the values
var valuesArray = [$feature.F2010, $feature.F2011, $feature.F2012, $feature.F2013];
// Specify the colors and corresponding value ranges in the color ramp
// For HEX values matching ArcGIS colors, visit: https://developers.arcgis.com/javascript/latest/visualization/symbols-color-ramps/esri-color-ramps/
function computeCellBackgroundColor(yearValue) {
var color = When(
yearValue < 5,
"#f5ffff",
yearValue <= 10 && yearValue > 5,
"#c8e7ff",
yearValue <= 15 && yearValue > 10,
"#9bd0ff",
yearValue <= 20 && yearValue > 15,
"#6db8ff",
yearValue <= 25 && yearValue > 20,
"#40a0ff",
yearValue <= 30 && yearValue > 25,
"#3b94eb",
yearValue <= 35 && yearValue > 30,
"#3687d7",
yearValue <= 40 && yearValue > 35,
"#307bc3",
yearValue <= 45 && yearValue > 40,
"#2b6eaf",
yearValue <= 50 && yearValue > 45,
"#2968a5",
yearValue <= 55 && yearValue > 50,
"#26629b",
yearValue <= 60 && yearValue > 55,
"#245b91",
yearValue > 60,
"#215587",
"grey"
);
return color;
}
// Define the color of the text in each cell, based on the background color
function computeCellTextcolor(yearValue) {
var color = When(
yearValue < 5,
"black",
yearValue <= 10 && yearValue > 5,
"black",
yearValue <= 15 && yearValue > 10,
"black",
yearValue <= 20 && yearValue > 15,
"black",
yearValue <= 25 && yearValue > 20,
"white",
yearValue <= 30 && yearValue > 25,
"white",
yearValue <= 35 && yearValue > 30,
"white",
yearValue <= 40 && yearValue > 35,
"white",
yearValue <= 45 && yearValue > 40,
"white",
yearValue <= 50 && yearValue > 45,
"white",
yearValue <= 55 && yearValue > 50,
"white",
yearValue <= 60 && yearValue > 55,
"white",
yearValue > 60,
"white",
"grey"
);
return color;
}
// NO USER MODIFICATION BELOW THIS LINE!
// Build the style string for the top cell
function buildTopCellStyle(width, textColor, backgroundColor) {
var cellStyle = 'style="';
cellStyle += "text-align:center;";
cellStyle += "font-size:24px;";
cellStyle += `width:${width};`;
cellStyle += `background:${backgroundColor};`;
cellStyle += `color:${textColor};`;
cellStyle += '"';
return cellStyle;
}
// Cell width in percent based on how many cells we have
var cellWidth = `${floor(100 / Count(yearsArray))}%`;
console("The width of each unit will be " + cellWidth);
// Assemble the top and bottom cells by iterating thru the years
var topCells = "";
var bottomCells = "";
for (var index in yearsArray) {
console("Building div for year " + yearsArray[index]);
console("The year value is " + valuesArray[index]);
// Assemble the top cell
var value = valuesArray[index];
var topCellTextColor = computeCellTextcolor(value);
var topCellBackgroundColor = computeCellBackgroundColor(value);
var topCellStyle = buildTopCellStyle(cellWidth, topCellTextColor, topCellBackgroundColor);
var topCell = `<td ${topCellStyle}><b>${value}</b></td>`;
console("Adding the following cell to the top cells" + topCell);
// Assemble the bottom cell
var bottomCell = `<td style="text-align:center;">${yearsArray[index]}</td>`;
console("Adding the following cell to the bottom cells" + bottomCell);
// Assemble to the top and bottom cells
topCells = topCells + topCell;
bottomCells = bottomCells + bottomCell;
}
var table = '<table style="width:100%;">';
table += `<tr>${topCells}</tr>`;
table += `<tr>${bottomCells}</tr>`;
table += "</table>";
return {
type: "text",
text: table
};
And a shout-out to @DaveNyenhuis for inspiration. He created a Dashboard list format that operates in a very similar fashion! And a shout out to @FredericAubry for the assistance with formatting and best practices!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.