arcgis-time-animation

ArcGIS Time Animation

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "arcgis-time-animation" with this command: npx skills add saschabrunnerch/arcgis-maps-sdk-js-ai-context/saschabrunnerch-arcgis-maps-sdk-js-ai-context-arcgis-time-animation

ArcGIS Time Animation

Use this skill for working with temporal data, time-aware layers, and time animation controls.

TimeExtent

Represents a time range with start and end dates.

import TimeExtent from "@arcgis/core/TimeExtent.js";

// Create time extent const timeExtent = new TimeExtent({ start: new Date("2024-01-01"), end: new Date("2024-12-31") });

// Apply to view view.timeExtent = timeExtent;

TimeExtent Properties

const timeExtent = new TimeExtent({ start: new Date("2024-01-01T00:00:00Z"), end: new Date("2024-06-30T23:59:59Z") });

console.log(timeExtent.start); // Date object console.log(timeExtent.end); // Date object

// Check if instant (start === end) if (timeExtent.start.getTime() === timeExtent.end.getTime()) { console.log("This is a time instant"); }

Null TimeExtent

// No time filter (show all data) view.timeExtent = null;

// Instant in time const instant = new TimeExtent({ start: new Date("2024-06-15"), end: new Date("2024-06-15") });

TimeInterval

Represents a duration of time.

import TimeInterval from "@arcgis/core/TimeInterval.js";

const interval = new TimeInterval({ value: 1, unit: "months" // milliseconds, seconds, minutes, hours, days, weeks, months, years });

TimeInterval Units

  • milliseconds

  • seconds

  • minutes

  • hours

  • days

  • weeks

  • months

  • years

  • decades

  • centuries

TimeSlider

Interactive widget for controlling temporal display.

TimeSlider Component

<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>

TimeSlider Widget (Core API)

import TimeSlider from "@arcgis/core/widgets/TimeSlider.js";

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") } });

TimeSlider with Playback

const timeSlider = new TimeSlider({ container: "timeSliderDiv", view: view, mode: "time-window", // instant, time-window, cumulative-from-start, cumulative-from-end fullTimeExtent: { start: new Date("2020-01-01"), end: new Date("2024-12-31") }, playRate: 1000, // Milliseconds between steps loop: true, stops: { interval: { value: 1, unit: "months" } } });

// Start/stop playback timeSlider.play(); timeSlider.stop();

TimeSlider Modes

// Instant - single point in time const instantSlider = new TimeSlider({ mode: "instant", fullTimeExtent: { start, end } });

// Time Window - range with start and end const windowSlider = new TimeSlider({ mode: "time-window", fullTimeExtent: { start, end } });

// Cumulative from Start - everything from start to current const cumulativeStart = new TimeSlider({ mode: "cumulative-from-start", fullTimeExtent: { start, end } });

// Cumulative from End - everything from current to end const cumulativeEnd = new TimeSlider({ mode: "cumulative-from-end", fullTimeExtent: { start, end } });

Custom Stops

// Interval-based stops const timeSlider = new TimeSlider({ stops: { interval: { value: 1, unit: "weeks" } } });

// Specific dates const timeSlider = new TimeSlider({ stops: { dates: [ new Date("2024-01-01"), new Date("2024-04-01"), new Date("2024-07-01"), new Date("2024-10-01") ] } });

// Number of stops (evenly distributed) const timeSlider = new TimeSlider({ stops: { count: 12 // 12 evenly spaced stops } });

TimeSlider Events

// Watch for time extent changes timeSlider.watch("timeExtent", (timeExtent) => { console.log("New time extent:", timeExtent.start, "to", timeExtent.end); updateCharts(timeExtent); });

// Watch for playback state timeSlider.watch("viewModel.state", (state) => { console.log("State:", state); // ready, playing, disabled });

TimeSlider Configuration

const timeSlider = new TimeSlider({ container: "timeSliderDiv", view: view, fullTimeExtent: { start: new Date("2020-01-01"), end: new Date("2024-12-31") },

// Display options layout: "auto", // auto, compact, wide tickConfigs: [{ mode: "position", values: [ new Date("2021-01-01"), new Date("2022-01-01"), new Date("2023-01-01"), new Date("2024-01-01") ], labelsVisible: true, labelFormatFunction: (value) => value.getFullYear().toString() }],

// Behavior playRate: 2000, loop: true,

// Labels 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" }); } });

Time-Aware Layers

FeatureLayer with Time

const featureLayer = new FeatureLayer({ url: "https://services.arcgis.com/.../FeatureServer/0", timeInfo: { startField: "event_date", // Field containing date endField: "end_date", // Optional end date field interval: { value: 1, unit: "days" } } });

// Check if layer supports time if (featureLayer.timeInfo) { console.log("Time field:", featureLayer.timeInfo.startField); console.log("Full extent:", featureLayer.timeInfo.fullTimeExtent); }

TimeInfo Properties

const timeInfo = { startField: "start_time", // Required: start date field endField: "end_time", // Optional: end date field (for duration) fullTimeExtent: { // Data's full time range start: new Date("2020-01-01"), end: new Date("2024-12-31") }, interval: { // Suggested animation interval value: 1, unit: "months" } };

ImageryLayer with Time

const imageryLayer = new ImageryLayer({ url: "https://services.arcgis.com/.../ImageServer", timeInfo: { startField: "acquisition_date" } });

// Multidimensional imagery const multidimLayer = new ImageryLayer({ url: "https://services.arcgis.com/.../ImageServer", multidimensionalDefinition: [{ variableName: "temperature", dimensionName: "StdTime", values: [1609459200000] // Epoch milliseconds }] });

MapImageLayer with Time

const mapImageLayer = new MapImageLayer({ url: "https://services.arcgis.com/.../MapServer", timeInfo: { startField: "date_field" } });

StreamLayer with Time

const streamLayer = new StreamLayer({ url: "wss://services.arcgis.com/.../StreamServer", timeInfo: { trackIdField: "vehicle_id", startField: "timestamp" }, purgeOptions: { displayCount: 1000, age: 5 // Minutes to keep } });

Initializing TimeSlider from Layer

// Auto-configure from time-aware layer await featureLayer.load();

const timeSlider = new TimeSlider({ container: "timeSliderDiv", view: view });

// Manually configure from layer if (featureLayer.timeInfo) { timeSlider.fullTimeExtent = featureLayer.timeInfo.fullTimeExtent; timeSlider.stops = { interval: featureLayer.timeInfo.interval }; }

TimeZoneLabel

Display time zone information.

TimeZoneLabel Component

<arcgis-map> <arcgis-time-zone-label slot="bottom-left"></arcgis-time-zone-label> </arcgis-map>

TimeZoneLabel Widget (Core API) - Deprecated

DEPRECATED since 4.33: Use the arcgis-time-zone-label component shown above instead. For information on widget deprecation, see Esri's move to web components.

// DEPRECATED - Use arcgis-time-zone-label component instead import TimeZoneLabel from "@arcgis/core/widgets/TimeZoneLabel.js";

const timeZoneLabel = new TimeZoneLabel({ view: view });

view.ui.add(timeZoneLabel, "bottom-left");

Filtering by Time

Client-Side Filter

// Apply time filter to view view.timeExtent = new TimeExtent({ start: new Date("2024-01-01"), end: new Date("2024-06-30") });

// Filter specific layer layerView.filter = { timeExtent: new TimeExtent({ start: new Date("2024-03-01"), end: new Date("2024-03-31") }) };

Query with Time

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);

Animation Patterns

Manual Animation Loop

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);

} }

// Usage animateOverTime( featureLayer, new Date("2024-01-01"), new Date("2024-12-31"), 7 // Weekly intervals );

TimeSlider with Statistics

// Update statistics panel as time changes 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; });

Synchronized TimeSliders

// Sync multiple time sliders const mainSlider = new TimeSlider({ container: "mainSliderDiv", view: mainView });

const compareSlider = new TimeSlider({ container: "compareSliderDiv", view: compareView });

// Sync them mainSlider.watch("timeExtent", (timeExtent) => { compareSlider.timeExtent = timeExtent; });

Historical Data Visualization

Track Lines

// Show movement paths with time const featureLayer = new FeatureLayer({ url: "https://.../tracks/FeatureServer/0", timeInfo: { startField: "timestamp", trackIdField: "vehicle_id" }, renderer: { type: "simple", symbol: { type: "simple-line", color: "blue", width: 2 } } });

Age-Based Styling

// Style features based on age const featureLayer = new FeatureLayer({ url: "...", renderer: { type: "simple", symbol: { type: "simple-marker", size: 8 }, visualVariables: [{ type: "color", field: "timestamp", stops: [ { value: Date.now() - 86400000, color: "red" }, // 1 day old { value: Date.now() - 604800000, color: "yellow" }, // 1 week old { value: Date.now() - 2592000000, color: "gray" } // 30 days old ] }] } });

Common Patterns

Full TimeSlider Setup

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" } } });

// Update UI on time change timeSlider.watch("timeExtent", (extent) => { document.getElementById("currentTime").textContent = ${extent.start.toLocaleDateString()} - ${extent.end.toLocaleDateString()}; });

return timeSlider; }

Time-Aware Query

async function queryByTimeRange(layer, startDate, endDate) { const query = layer.createQuery(); query.timeExtent = new TimeExtent({ start: startDate, end: endDate }); query.outFields = ["*"]; query.returnGeometry = true;

return await layer.queryFeatures(query); }

// Usage const marchData = await queryByTimeRange( featureLayer, new Date("2024-03-01"), new Date("2024-03-31") );

Time-Based Highlighting

// Highlight features from current time period timeSlider.watch("timeExtent", async (timeExtent) => { // Clear previous highlights if (highlightHandle) { highlightHandle.remove(); }

// Query features in current time extent const query = featureLayer.createQuery(); query.timeExtent = timeExtent;

const layerView = await view.whenLayerView(featureLayer); const results = await featureLayer.queryFeatures(query);

highlightHandle = layerView.highlight(results.features); });

TypeScript Usage

Time configurations use autocasting. For TypeScript safety, use as const :

// Use 'as const' for time slider configuration const timeSlider = new TimeSlider({ view: view, mode: "time-window", stops: { interval: { value: 1, unit: "hours" } } as const });

// For layer time settings layer.timeInfo = { startField: "start_date", endField: "end_date", interval: { value: 1, unit: "days" } } as const;

Tip: See arcgis-core-maps skill for detailed guidance on autocasting vs explicit classes.

Reference Samples

  • timeslider

  • Basic TimeSlider widget usage

  • timeslider-filter

  • Filtering data with TimeSlider

  • timeslider-component-filter

  • TimeSlider component with filtering

  • time-layer

  • Working with time-aware layers

Common Pitfalls

Time Zone Issues: Dates are affected by time zones

// Use UTC dates for consistency const date = new Date("2024-06-15T00:00:00Z");

// Or specify timezone const localDate = new Date("2024-06-15T00:00:00-05:00");

Layer Must Be Loaded: TimeInfo is only available after loading

await layer.load(); if (layer.timeInfo) { // Now timeInfo is available }

TimeExtent Not Applied: View's timeExtent must be set

// Set on view to filter all time-aware layers view.timeExtent = timeExtent;

// Or on specific layerView for per-layer filtering layerView.filter = { timeExtent };

Null vs Undefined: Use null to show all data

// Show all data (no time filter) view.timeExtent = null;

Performance: Large time ranges can be slow

// Consider using time-based queries instead of filtering const query = layer.createQuery(); query.timeExtent = smallerTimeRange;

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

arcgis-widgets-ui

No summary provided by upstream source.

Repository SourceNeeds Review
General

arcgis-popup-templates

No summary provided by upstream source.

Repository SourceNeeds Review
General

arcgis-geometry-operations

No summary provided by upstream source.

Repository SourceNeeds Review
General

arcgis-authentication

No summary provided by upstream source.

Repository SourceNeeds Review