Item page
CodePen
Sandbox Download

Incidents styled with visual variables and clusters to show the number of days required to close each complaint.

What are time styles?

Time styles include all visualizations that involve date/time data. You can use these styles to visualize when and where an event occurs. Common examples involve the following:

  1. Timeline
  2. Before and after
  3. Age
  4. Tracks
  5. Time series animation

Examples

Timeline

A timeline visualization displays date/time data along a continuous color ramp. It provides an immediate view at when phenomena occurred or when a value was recorded relative to all other data points.

Item page
CodePen
Sandbox Download
Hurricane observations are colored by their date in the 2000 Atlantic hurricane season.
Time - timeline
20 collapsed lines
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<title>Time - timeline</title>
<!-- Load the ArcGIS Maps SDK for JavaScript from CDN -->
<script type="module" src="https://js.arcgis.com/5.2/"></script>
<style>
html,
body {
height: 100%;
margin: 0;
}
</style>
</head>
<body>
<arcgis-map item-id="3378391741d54e81aa1c3443f6aa6dca">
<arcgis-zoom slot="top-left"></arcgis-zoom>
<arcgis-expand slot="top-right" expanded>
<arcgis-legend></arcgis-legend>
</arcgis-expand>
</arcgis-map>
2 collapsed lines
</body>
</html>

Before and after

You can use a color visual variable with a diverging color ramp to visualize which events occurred before and after a specific date.

Item page
CodePen
Sandbox Download
Hurricane observations are colored by whether they occurred before or after July 1, 2013.
Time - before and after
20 collapsed lines
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<title>Time - before and after</title>
<!-- Load the ArcGIS Maps SDK for JavaScript from CDN -->
<script type="module" src="https://js.arcgis.com/5.2/"></script>
<style>
html,
body {
height: 100%;
margin: 0;
}
</style>
</head>
<body>
<arcgis-map item-id="b39ae97a580745369ac01daf44a119cb">
<arcgis-zoom slot="top-left"></arcgis-zoom>
<arcgis-expand slot="bottom-left" expanded>
<arcgis-legend></arcgis-legend>
</arcgis-expand>
</arcgis-map>
2 collapsed lines
</body>
</html>

Age

An age visualization shows the age of a feature (or the elapsed time up to a meaningful date or the current date) based on a date field. Age visualizations may be applied in the following scenarios:

  1. How long has an asset been in commission?
  2. How old is the incident report?
  3. How long has it been since the last inspection?
  4. Is an incident past due for resolution?

Age is typically defined using the DateDiff function in an Arcade expression and mapped with a color or size variable. It specifies a length of time with desired units.

valueExpression = "DateDiff( Now(), $feature.date_created, 'hours' )";
Map Viewer does not support overriding continuous color ramp labels. The custom labels shown in the JavaScript example must be configured in code.
Item page
CodePen
Sandbox Download
Street condition complaints are colored by the time required to close each incident.
Time - age
20 collapsed lines
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<title>Time - age</title>
<!-- Load the ArcGIS Maps SDK for JavaScript from CDN -->
<script type="module" src="https://js.arcgis.com/5.2/"></script>
<style>
html,
body {
height: 100%;
margin: 0;
}
</style>
</head>
<body>
<arcgis-map item-id="447da8026c56461b9b4dcc7249b270c1">
<arcgis-zoom slot="top-left"></arcgis-zoom>
<arcgis-expand slot="top-right" expanded>
<arcgis-legend></arcgis-legend>
</arcgis-expand>
</arcgis-map>
2 collapsed lines
</body>
</html>

Tracks

Track data is represented as a series of observations (typically points). In addition to a timestamp, each observation must belong to a track identified by a unique ID. This ID is used to group observations into a track. To render track data, the layer must be configured with a valid timeInfo.

The timeInfo property of the layer defines the following:

  • startField: The field representing the time the observation occurred.
  • trackIdField: The field containing the unique ID of the track the observation belongs to.
layer.timeInfo = {
startField: "ISO_time",
trackIdField: "Serial_Num",
};

Historic hurricane locations can be represented as points. To render their tracks as paths, set the trackInfo property of the layer. The trackInfo property defines the following properties:

  • previousObservations: Defines how to render the previous observations of the track. Previous locations can use simple markers with color and size visual variables to indicate hurricane strength.
  • latestObservations: Defines how to render the latest observations of the track relative to the time slider. Latest hurricane observations can use animated hurricane-shaped markers with a size visual variable to indicate hurricane strength.
  • trackLine: Defines how to render the track line. A track line can use a simple line symbol.

The renderers listed above also include opacity visual variables to indicate the age of the observation relative to the time slider. The older the observation, the more transparent it appears until it fades out completely.

This requires a TimeSlider component for control over the time.

This cannot be configured in Map Viewer alone. Instead, create the map in Map Viewer, then use JavaScript for the rest of the configuration.
Sample Code page
CodePen
Sandbox Download

Historic hurricane tracks use a time slider to show previous positions relative to the current observation.

The basic trackInfo configuration is stubbed out below. Open the code editor above to see the full configuration.

layer.trackInfo = {
previousObservations: {
renderer: {
// renderer configuration defined here
},
labelingInfo: [
// labelingInfo configuration defined here
],
},
latestObservations: {
renderer: {
// renderer configuration defined here
},
labelingInfo: [
// labelingInfo configuration defined here
],
},
trackLine: {
renderer: {
// renderer configuration defined here
},
labelingInfo: [
// labelingInfo configuration defined here
],
},
};

Time series animation

Time series animations are visualizations showing how data values change over time in features fixed at unchanging locations. These typically involve a time slider so users have the ability to explore moments of time or time windows.

For features that have a static position (such as sensors, buildings, countries, etc.), but have attributes that vary over time (e.g. POPULATION_2000, POPULATION_2005, POPULATION_2010, etc.), Arcade expressions can access time slider values to dynamically reference the field name corresponding to the current time on the slider. This allows you to visualize how data changes over time without needing to filter features or download duplicate geometries.

The underlying rendering engine re-executes the expression with every slider value change.

This cannot be configured in Map Viewer alone. Instead, create the map in Map Viewer, then use JavaScript for the rest of the configuration.
Sample Code page Item page
CodePen
Sandbox Download

The time slider selects temperature-anomaly fields from F1900 through F2020 so the map updates year by year.

First, configure the time slider to match the start and end dates of the data with the appropriate time interval.

Configure the time bar
18 collapsed lines
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<title>Time | Sample | ArcGIS Maps SDK for JavaScript</title>
<!-- Load the ArcGIS Maps SDK for JavaScript from CDN -->
<script type="module" src="https://js.arcgis.com/5.2/"></script>
</head>
<body>
<calcite-shell>
<arcgis-map item-id="74a5a5d2e6784ef19578cbce8c808886">
<arcgis-zoom slot="top-right"></arcgis-zoom>
<arcgis-legend slot="top-left"></arcgis-legend>
</arcgis-map>
<calcite-shell-panel slot="panel-bottom">
<arcgis-time-bar
mode="instant"
show-play
show-next
show-previous
show-time-extent
reference-element="arcgis-map"
>
<arcgis-time-bar-slider slot="time-extent" show-ticks show-min show-max popover-display="always">
</arcgis-time-bar-slider>
</arcgis-time-bar>
68 collapsed lines
</calcite-shell-panel>
</calcite-shell>
<script type="module">
const TimeInterval = await $arcgis.import("@arcgis/core/time/TimeInterval.js");
const viewElement = document.querySelector("arcgis-map");
await viewElement.viewOnReady();
const timeBar = document.querySelector("arcgis-time-bar");
timeBar.fullTimeExtent = {
start: new Date(1880, 0, 1),
end: new Date(2018, 0, 1),
};
timeBar.timeExtent = {
start: new Date(1880, 0, 1),
end: new Date(1880, 0, 1),
};
timeBar.stops = {
interval: new TimeInterval({
value: 1,
unit: "years",
}),
};
const view = viewElement.view;
const layer = view.map.layers.getItemAt(0);
const renderer = layer.renderer.clone();
const sizeVisualVariable = renderer.visualVariables.find((visualVariable) => visualVariable.type === "size");
// Returns the value of the "F{year}" field based on the time bar slider's value.
// This expression will re-execute every time the time bar slider's value changes
const valueExpression = `
Expects($feature, "F*");
if(HasValue($view, ["timeProperties", "currentEnd"])){
var y = Year($view.timeProperties.currentEnd);
var value = $feature["F" + y];
return value;
}
return null;
`;
// Update legend text to be more user friendly
const valueExpressionTitle = "Are temperatures significantly warmer or colder than normal?";
// Replace the field with the valueExpression so the user can dynamically
// explore the data as it changed from year to year
renderer.field = null;
renderer.valueExpression = valueExpression;
renderer.valueExpressionTitle = valueExpressionTitle;
// Since this is an above-and-below size renderer, we need to update
// the size visual variable to reflect the new valueExpression
sizeVisualVariable.field = null;
sizeVisualVariable.valueExpression = valueExpression;
sizeVisualVariable.valueExpressionTitle = valueExpressionTitle;
// Update legend text to be more user friendly
sizeVisualVariable.stops[0].label = "Colder";
sizeVisualVariable.stops[2].label = "Normal";
sizeVisualVariable.stops[4].label = "Warmer";
renderer.visualVariables = [sizeVisualVariable];
layer.renderer = renderer;
</script>
</body>
</html>

Next, update the layer’s renderer to use an Arcade expression that references the time slider value to dynamically access the field name for the year represented by the slider value.

Update the renderer for the selected year
57 collapsed lines
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<title>Time | Sample | ArcGIS Maps SDK for JavaScript</title>
<!-- Load the ArcGIS Maps SDK for JavaScript from CDN -->
<script type="module" src="https://js.arcgis.com/5.2/"></script>
</head>
<body>
<calcite-shell>
<arcgis-map item-id="74a5a5d2e6784ef19578cbce8c808886">
<arcgis-zoom slot="top-right"></arcgis-zoom>
<arcgis-legend slot="top-left"></arcgis-legend>
</arcgis-map>
<calcite-shell-panel slot="panel-bottom">
<arcgis-time-bar
mode="instant"
show-play
show-next
show-previous
show-time-extent
reference-element="arcgis-map"
>
<arcgis-time-bar-slider slot="time-extent" show-ticks show-min show-max popover-display="always">
</arcgis-time-bar-slider>
</arcgis-time-bar>
</calcite-shell-panel>
</calcite-shell>
<script type="module">
const TimeInterval = await $arcgis.import("@arcgis/core/time/TimeInterval.js");
const viewElement = document.querySelector("arcgis-map");
await viewElement.viewOnReady();
const timeBar = document.querySelector("arcgis-time-bar");
timeBar.fullTimeExtent = {
start: new Date(1880, 0, 1),
end: new Date(2018, 0, 1),
};
timeBar.timeExtent = {
start: new Date(1880, 0, 1),
end: new Date(1880, 0, 1),
};
timeBar.stops = {
interval: new TimeInterval({
value: 1,
unit: "years",
}),
};
const view = viewElement.view;
const layer = view.map.layers.getItemAt(0);
const renderer = layer.renderer.clone();
const sizeVisualVariable = renderer.visualVariables.find((visualVariable) => visualVariable.type === "size");
// Returns the value of the "F{year}" field based on the time bar slider's value.
// This expression will re-execute every time the time bar slider's value changes
const valueExpression = `
Expects($feature, "F*");
if(HasValue($view, ["timeProperties", "currentEnd"])){
var y = Year($view.timeProperties.currentEnd);
var value = $feature["F" + y];
return value;
}
return null;
`;
// Update legend text to be more user friendly
const valueExpressionTitle = "Are temperatures significantly warmer or colder than normal?";
// Replace the field with the valueExpression so the user can dynamically
// explore the data as it changed from year to year
renderer.field = null;
renderer.valueExpression = valueExpression;
renderer.valueExpressionTitle = valueExpressionTitle;
// Since this is an above-and-below size renderer, we need to update
// the size visual variable to reflect the new valueExpression
sizeVisualVariable.field = null;
sizeVisualVariable.valueExpression = valueExpression;
sizeVisualVariable.valueExpressionTitle = valueExpressionTitle;
// Update legend text to be more user friendly
sizeVisualVariable.stops[0].label = "Colder";
sizeVisualVariable.stops[2].label = "Normal";
sizeVisualVariable.stops[4].label = "Warmer";
renderer.visualVariables = [sizeVisualVariable];
layer.renderer = renderer;
3 collapsed lines
</script>
</body>
</html>

API support

  1. Color only
  2. Size variable creators only supported for points
  3. Size variable creators not supported in 3D