Work with temporal data using TimeSlider, TimeExtent, TimeInterval, and time-aware layers. Use for animating data over time, filtering by date ranges, and visualizing temporal patterns.
80
75%
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Advisory
Suggest reviewing before use
Optimize this skill with Tessl
npx tessl skill review --optimize ./contexts/5.0/skills/arcgis-time-animation/SKILL.mdUse this skill for temporal data, time-aware layers, time filtering, and animation controls.
import TimeExtent from "@arcgis/core/TimeExtent.js";
import TimeInterval from "@arcgis/core/TimeInterval.js";
import TimeSlider from "@arcgis/core/widgets/TimeSlider.js";const TimeExtent = await $arcgis.import("@arcgis/core/TimeExtent.js");
const TimeInterval = await $arcgis.import("@arcgis/core/TimeInterval.js");
const TimeSlider = await $arcgis.import("@arcgis/core/widgets/TimeSlider.js");Represents a time range with start and end dates.
const timeExtent = new TimeExtent({
start: new Date("2024-01-01"),
end: new Date("2024-12-31")
});
// Apply to view (filters all time-aware layers)
view.timeExtent = timeExtent;
// Instant in time (start === end)
const instant = new TimeExtent({
start: new Date("2024-06-15"),
end: new Date("2024-06-15")
});
// No time filter (show all data)
view.timeExtent = null;Represents a duration of time.
const interval = new TimeInterval({
value: 1,
unit: "months"
});Supported units: milliseconds, seconds, minutes, hours, days, weeks, months, years, decades, centuries
<arcgis-map item-id="YOUR_WEBMAP_ID">
<arcgis-time-slider
slot="bottom-left"
mode="time-window"
loop
time-visible>
</arcgis-time-slider>
</arcgis-map>
<script type="module">
const map = document.querySelector("arcgis-map");
const timeSlider = document.querySelector("arcgis-time-slider");
await map.viewOnReady();
// Configure from layer
const layer = map.view.map.layers.find(l => l.timeInfo);
if (layer) {
await layer.load();
timeSlider.fullTimeExtent = layer.timeInfo.fullTimeExtent;
timeSlider.stops = { interval: layer.timeInfo.interval };
}
</script>const timeSlider = new TimeSlider({
container: "timeSliderDiv",
view: view,
fullTimeExtent: {
start: new Date("2020-01-01"),
end: new Date("2024-12-31")
},
timeExtent: {
start: new Date("2024-01-01"),
end: new Date("2024-03-31")
},
mode: "time-window",
playRate: 1000,
loop: true,
stops: {
interval: {
value: 1,
unit: "months"
}
}
});| Property | Type | Default | Description |
|---|---|---|---|
fullTimeExtent | TimeExtent | — | Complete time range the widget can display |
timeExtent | TimeExtent | — | Currently selected time range |
mode | string | "instant" | Animation mode |
stops | object | — | Snap points for slider |
playRate | number | 1000 | Milliseconds between steps |
loop | boolean | false | Restart at end |
layout | string | "auto" | "auto", "compact", "wide" |
disabled | boolean | false | Disable interaction |
// Instant - single point in time
mode: "instant"
// Time Window - range with start and end
mode: "time-window"
// Cumulative from Start - everything from start to current
mode: "cumulative-from-start"
// Cumulative from End - everything from current to end
mode: "cumulative-from-end"// Interval-based stops
stops: {
interval: { value: 1, unit: "weeks" }
}
// Specific dates
stops: {
dates: [
new Date("2024-01-01"),
new Date("2024-04-01"),
new Date("2024-07-01"),
new Date("2024-10-01")
]
}
// Number of evenly distributed stops
stops: {
count: 12
}timeSlider.play();
timeSlider.stop();timeSlider.watch("timeExtent", (timeExtent) => {
console.log("New time range:", timeExtent.start, "to", timeExtent.end);
});
timeSlider.watch("viewModel.state", (state) => {
console.log("State:", state); // "ready", "playing", "disabled"
});const timeSlider = new TimeSlider({
container: "timeSliderDiv",
view: view,
fullTimeExtent: { start, end },
tickConfigs: [{
mode: "position",
values: [
new Date("2021-01-01"),
new Date("2022-01-01"),
new Date("2023-01-01")
],
labelsVisible: true,
labelFormatFunction: (value) => value.getFullYear().toString()
}],
labelFormatFunction: (value, type, element, layout) => {
const date = new Date(value);
if (type === "min" || type === "max") {
return date.toLocaleDateString();
}
return date.toLocaleDateString("en-US", { month: "short", year: "numeric" });
}
});const featureLayer = new FeatureLayer({
url: "https://services.arcgis.com/.../FeatureServer/0",
timeInfo: {
startField: "event_date",
endField: "end_date",
interval: {
value: 1,
unit: "days"
}
}
});
// Check if layer supports time
await featureLayer.load();
if (featureLayer.timeInfo) {
console.log("Time field:", featureLayer.timeInfo.startField);
console.log("Full extent:", featureLayer.timeInfo.fullTimeExtent);
}| Property | Type | Description |
|---|---|---|
startField | string | Start date field name (required) |
endField | string | End date field name (optional) |
fullTimeExtent | TimeExtent | Complete time range of data |
interval | TimeInterval | Suggested animation interval |
trackIdField | string | Track identifier field (for StreamLayer) |
// ImageryLayer
const imageryLayer = new ImageryLayer({
url: "...",
timeInfo: { startField: "acquisition_date" }
});
// MapImageLayer
const mapImageLayer = new MapImageLayer({
url: "...",
timeInfo: { startField: "date_field" }
});
// StreamLayer
const streamLayer = new StreamLayer({
url: "wss://services.arcgis.com/.../StreamServer",
timeInfo: {
trackIdField: "vehicle_id",
startField: "timestamp"
},
purgeOptions: {
displayCount: 1000,
age: 5
}
});async function setupTimeSlider(view, layer) {
await layer.load();
if (!layer.timeInfo) {
console.warn("Layer is not time-aware");
return null;
}
const timeSlider = new TimeSlider({
container: "timeSliderDiv",
view: view,
fullTimeExtent: layer.timeInfo.fullTimeExtent,
mode: "time-window",
playRate: 1000,
loop: true,
stops: {
interval: layer.timeInfo.interval || { value: 1, unit: "months" }
}
});
timeSlider.watch("timeExtent", (extent) => {
document.getElementById("currentTime").textContent =
`${extent.start.toLocaleDateString()} - ${extent.end.toLocaleDateString()}`;
});
return timeSlider;
}// Filter all time-aware layers via view
view.timeExtent = new TimeExtent({
start: new Date("2024-01-01"),
end: new Date("2024-06-30")
});
// Filter specific layer via layerView
const layerView = await view.whenLayerView(featureLayer);
layerView.filter = {
timeExtent: new TimeExtent({
start: new Date("2024-03-01"),
end: new Date("2024-03-31")
})
};const query = featureLayer.createQuery();
query.timeExtent = new TimeExtent({
start: new Date("2024-01-01"),
end: new Date("2024-12-31")
});
query.where = "status = 'active'";
query.returnGeometry = true;
const results = await featureLayer.queryFeatures(query);timeSlider.watch("timeExtent", async (timeExtent) => {
const query = featureLayer.createQuery();
query.timeExtent = timeExtent;
query.outStatistics = [{
statisticType: "count",
onStatisticField: "OBJECTID",
outStatisticFieldName: "count"
}, {
statisticType: "sum",
onStatisticField: "value",
outStatisticFieldName: "total"
}];
const result = await featureLayer.queryFeatures(query);
const stats = result.features[0].attributes;
document.getElementById("count").textContent = stats.count;
document.getElementById("total").textContent = stats.total;
});let highlightHandle;
timeSlider.watch("timeExtent", async (timeExtent) => {
if (highlightHandle) highlightHandle.remove();
const query = featureLayer.createQuery();
query.timeExtent = timeExtent;
const layerView = await view.whenLayerView(featureLayer);
const results = await featureLayer.queryFeatures(query);
highlightHandle = layerView.highlight(results.features);
});async function animateOverTime(layer, startDate, endDate, intervalDays) {
const current = new Date(startDate);
while (current <= endDate) {
const nextDate = new Date(current);
nextDate.setDate(nextDate.getDate() + intervalDays);
view.timeExtent = new TimeExtent({
start: current,
end: nextDate
});
await new Promise(resolve => setTimeout(resolve, 500));
current.setDate(current.getDate() + intervalDays);
}
}<arcgis-map>
<arcgis-time-zone-label slot="bottom-left"></arcgis-time-zone-label>
</arcgis-map>// Set time visibility on individual graphics
graphic.visibilityTimeExtent = new TimeExtent({
start: new Date("2024-01-01"),
end: new Date("2024-06-30")
});Time zone issues: Dates are affected by JavaScript's local timezone — use UTC dates for consistency.
const date = new Date("2024-06-15T00:00:00Z");Layer must be loaded: timeInfo is only available after await layer.load().
TimeExtent not applied: The view's timeExtent must be set to filter all time-aware layers.
Null removes filter: Use view.timeExtent = null to show all data (no time filter).
Performance: Large time ranges can return many features — use server-side queries when possible.
Stops required: TimeSlider needs stops configured to define slider positions.
timeslider — Basic TimeSlider widgettimeslider-filter — Filtering data with TimeSlidertimeslider-component-filter — TimeSlider component with filteringtime-layer — Working with time-aware layerswidgets-timeslider — TimeSlider widget exampleswidgets-timeslider-offset — TimeSlider with timezone offsetlayers-scenelayer-time — Time-aware SceneLayerlayers-voxel-time — Time-aware VoxelLayerlayers-graphics-visibilitytimeextent — Graphics visibility with timearcgis-imagery — Multidimensional imagery with timearcgis-layers — Layer configurationarcgis-widgets-ui — Widget placement and slotsd84407b
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.