Some visualizations animate, pulse, and flash. If you're sensitive to motion or flashing, turn on Reduce motion in your system settings.

poopdeck.gl
deck.gl Layers

AnimatedArcLayer

The AnimatedArcLayer renders origin→destination flows as bowed arcs, animated by the time window. Each tile feature is a 2-vertex LineString — the layer reads the FIRST vertex as the arc's source and the LAST as its target, derives instanced getSourcePosition/getTargetPosition buffers once per tile, and draws through deck.gl's ArcLayer (@deck.gl/layers). No special "arc" tile type is needed: any LineString archive whose features collapse to endpoints works, but the natural producer is stt-generate nyc-rideshare --od, which emits straight pickup→dropoff lines (no routing).

It extends SpatioTemporalLayer and reuses all of its archive/tileset plumbing. Time filtering is window-mode via the shared TimeFilterExtension: an arc is shown (with optional fade) while its [startTime, endTime] overlaps the current window — for taxi data, the pickup→dropoff interval.

Installation#

import { AnimatedArcLayer } from '@poopdeck.gl/layers';

Usage#

const layer = new AnimatedArcLayer({
id: 'od-arcs',
data: '/data/nyc-od-arcs/manifest.json',
currentTime,
timeWindow: 30 * 60 * 1000, // 30-min slice
sourceColor: [56, 196, 232, 210], // origin — cyan
targetColor: [255, 142, 64, 220], // destination — orange
width: 1.5,
arcHeight: 0.4,
});

Properties#

Inherits all properties from SpatioTemporalLayer.

PropertyTypeDefaultDescription
sourceColorColor | string[0,150,255,255]Origin-end color: a constant RGBA or a categorical property-column name (GPU CategoryColorExtension).
targetColorColor | string[255,127,14,255]Destination-end color; the arc interpolates source→target.
getSourceColor / getTargetColorColor | stringUpstream-vocabulary aliases (constant or column name; a function warns once and falls back).
width / getWidthnumber | string2Arc width — constant or per-feature numeric column.
widthUnits'pixels' | 'meters' | 'common''pixels'Width units.
widthScalenumber1Global multiplier for arc widths (ArcLayer pass-through).
widthMinPixelsnumber0Clamp arc width to at least this many on-screen pixels.
widthMaxPixelsnumberMAX_SAFE_INTEGERClamp arc width to at most this many on-screen pixels.
greatCirclebooleanfalseBow arcs along a great-circle path (long-haul / globe flows).
numSegmentsnumber50Arc tessellation segment count — higher is smoother, lower is cheaper (ArcLayer pass-through).
arcHeight / getHeightnumber | string1Arc height multiplier; 0 = flat. Constant or a per-feature numeric column name — upstream registers instanceHeights as an ordinary per-instance accessor, so a baked column rides it zero-copy exactly like width.
arcTilt / getTiltnumber | string0Sideways tilt (degrees) to separate arcs sharing endpoints. Constant or a per-feature numeric column name (instanceTilts is likewise a per-instance accessor upstream) — a column is what actually separates overlapping flows on the same OD pair.
colorPaletteColor[]10-stopPalette for a categorical sourceColor/targetColor column, indexed by first-seen category order within each tile.
colorMappingRecord<string, Color> | nullnullExplicit category-string → color map, projected onto each tile's own dictionary so a category keeps ONE color across tiles. Takes precedence over colorPalette when set.
colorMappingDefaultColor[120,120,120,255]Fallback color for categories absent from colorMapping.
filterPropertystring | nullnullName of a baked numeric column to GPU-filter arcs by (STTDataFilterExtension); composes WITH the time filter — an arc must pass both. Accessor-alias of deck's getFilterValue: a column NAME, not a function. Unset ⇒ the extension is not installed at all. A tile lacking the column renders unfiltered.
filterRange[number, number] | nullnullInclusive [min, max] bounds for filterProperty. null idles the filter (renders all) while keeping the column bound, so a range set later animates by uniform with no tile re-preparation.
filterSoftRange[number, number] | nullnullOptional soft [min, max] inside filterRange for a fade instead of a hard clip. No effect unless filterProperty + filterRange are set.
filterEnabledbooleantrueEnable/disable the column filter without dropping the bound attribute. Effective only with filterProperty + a valid filterRange.
fadeInDuration / fadeOutDurationnumber300Window fade ramps (ms).

Single-channel categorical color: because CategoryColorExtension injects one category index, a categorical column colors the WHOLE arc one color (source wins if both name a column), not independent source/target categories.

Behavior notes#

  • LineString tiles only: the layer checks each tile layer's geometryType and skips any layer that is not LineString, emitting one named console warning rather than misreading a point/polygon buffer. Tiles predating the geometry-kind tag are trusted, with a structural startIndices backstop behind them.
  • Source/target derivation: deriveSourceTargetPositions walks each feature's startIndices, copying the first vertex → dense source and the last → dense target (both featureCount × dims). Multi-vertex polylines collapse to their endpoints.
  • Accessor aliases: getHeight/getTilt (and getWidth, getSourceColor, getTargetColor) take a constant or a property-column NAME, never a function accessor — a function warns once and falls back to the legacy prop.
  • Picking: hits carry the feature's decoded properties on info.object and the source tile on info.tile.

The sublayer short id for _subLayerProps overrides is arcs.

Source#

packages/layers/src/layers/core/animated-arc-layer.ts · shared endpoint helper: od-positions.ts