pixi-heatmap logopixi-heatmap v0.4.0

pixi-heatmap

Smooth GPU heatmaps for PixiJS v8 — one code path for WebGL + WebGPU, from static datasets to extreme streaming workloads.

Installation

Usage

Create a HeatmapLayer, feed it points, add it to the stage, and call update(renderer) every frame — it's dirty-gated, so unchanged frames cost nothing.

Options

Everything is optional except width and height.

Dynamic updates

Stream points in over time — with decay the heat fades, which is ideal for cursor trails and live data.

Interaction

Choose direct Pixi transforms in Manual mode or pixi-viewport as the camera driver. Both paths render the same 150k NYC taxi pickups and preserve the same screen-stable heat field across pan, zoom, and rotation: ⌘/Ctrl + scroll to zoom, middle-drag to pan (touch: drag and pinch). The palette controls start from the library default, update its four visible color stops live, and generate perceptually spaced random palettes.

pixi-viewport driver code

Aggregate capacity benchmark

Every value-1 record enters addPoints() and contributes to a fixed 2px grid. Select 1M, 100M, or 1B; preparation progress and ETA measure the complete input workload. The retained field continuously sweeps 0.6×–6× zoom while panning, with a Manual camera available for direct control.

API Reference

HeatmapLayerOptions

widthnumber

Width of the heatmap in pixels. Required.

heightnumber

Height of the heatmap in pixels. Required.

optimization'manual' | 'auto' Default is 'manual'

Coordinate precision, normalization, tone mapping, aggregation, Worker use, and resolution from camera range, data size, device capacity, transform activity, and frame time. Explicit options remain authoritative.

radiusnumber Default is 25

Kernel radius of each point, in pixels.

minZoomnumber

Lower bound for the effective zoom used by kernel compensation and radius-derived aggregation.

maxZoomnumber

Upper bound for the effective zoom used by kernel compensation and radius-derived aggregation.

gradientRecord<number, string> Default is blue → red ramp

Color ramp stops as offset → color, from 0 (cold) to 1 (hot).

maxIntensitynumber | 'auto' Default is 10

Intensity mapped to the top of the ramp; auto optimization supplies 'auto'.

toneMapping'linear' | 'adaptive' Default is 'linear'

Transfer normalized density into the gradient. Auto optimization supplies adaptive peak compression so weak positive density stays visible.

accumulationPrecision'balanced' | 'high' Default is 'balanced'

Auto optimization supplies high precision; capable devices use 32-bit float accumulation.

webgpuDensity'auto' | 'raster' | 'gather' Default is 'auto'

Select instanced raster accumulation or the tiled WebGPU compute gather. Auto compares point, accumulation-pixel, and kernel work for each supported direct field.

resolutionnumber | 'adaptive' Default is 'adaptive'

Accumulation buffer scale; 'adaptive' lowers it under load to hold frame rate.

aggregationboolean Default is true

Keep smaller radius-following datasets as raw splats, then use a continuous bilinear grid under larger loads.

aggregationCellSizenumber Default is radius / 4

Use fixed weighted-centroid bins at this local-pixel cell size.

pointStorage'retained' | 'aggregate' Default is 'retained'

Retain every source record, or incrementally fold append batches into a fixed Cloud-in-Cell grid whose memory depends on fixed layer bounds and aggregation cell size.

workerboolean | 'auto' Default is 'auto'

Offload aggregation to a Web Worker; 'auto' uses one when the browser supports it.

decaynumber Default is 0

Per-frame heat decay; values above 0 fade old heat over time.

minOpacitynumber Default is 0

Opacity floor for faint areas, so sparse data stays visible.

Methods

optimizationProfile exposes the current heuristic and effective option decisions. A bounded zoom span of at least 8× with up to 160,000 active points on a desktop-sized instance chunk selects direct splats at fixed full resolution. Other sources use radius-following aggregation and adaptive resolution. The profile also reports the active tone-mapping exponent.

setPoints(points)(points: HeatmapPoint[]) => void

Replace the dataset; each point is { x, y, value? } with finite coordinates and a finite, non-negative value.

setRaw(points, count?)(points: Float32Array, count?: number) => void

Replace the dataset from interleaved (x, y, weight) triples using finite coordinates and finite, non-negative weights; this path validates every record and copies the active triples into retained storage.

setRawTrusted(points, statistics)(points: Float32Array, statistics: HeatmapTrustedRawOptions) => void

Borrow caller-validated, strictly positive interleaved triples with exact precomputed weight statistics. Retained point storage with decay 0 gives this streaming path O(1) ingestion.

addPoint(point)(point: HeatmapPoint) => void

Append a single point without replacing the dataset.

addPoints(points, count?)(points: HeatmapPoint[] | Float32Array, count?: number) => void

Append an object array or interleaved typed batch in one call. Aggregate point storage folds the batch into its persistent field during ingestion.

pointCount / totalWeight / renderPointCountnumber

Read the accepted representative count, summed contribution weight, and retained GPU splat count.

aggregateStorageBytesnumber | null

Read fixed-grid CPU storage in aggregate mode; retained mode reports null.

densityEngine / webgpuGatherStatsstring / WebgpuGatherStats

Read the latest complete density engine and the WebGPU compute dispatch, fallback, grid, and capability diagnostics.

clear()() => void

Remove all points.

moveTo(x, y) / moveBy(dx, dy)(...values: number[]) => void

Set or offset the layer position in parent coordinates.

zoomTo(scale, x?, y?) / zoomBy(factor, x?, y?)(...values: number[]) => void

Set or multiply display scale while keeping the optional parent-space anchor fixed.

rotateTo(radians, x?, y?) / rotateBy(delta, x?, y?)(...values: number[]) => void

Set or add rotation while keeping the optional parent-space anchor fixed.

setOpacity(opacity)(opacity: number) => void

Set the display alpha from 0 to 1.

setZoom(zoom)(zoom: number) => void

Pin the kernel scaling manually and stop following ancestor transforms. By default the layer auto-tracks its worldTransform scale, which keeps on-screen density stable inside scaled parents such as pixi-viewport. Configured minZoom and maxZoom clamp this effective value while display transforms keep scaling.

resumeAutoZoom()() => void

Re-enable worldTransform tracking after a manual setZoom().

resize(width, height)(width: number, height: number) => void

Resize retained-source layers and their accumulation buffers. Aggregate point storage uses fixed dimensions and a new layer for a different size.

update(renderer)(renderer: Renderer) => void

Flush pending changes to the GPU; dirty-gated, call every frame.

destroy()() => void

Release all GPU resources.

Credits

Built on PixiJS. The accumulation-and-ramp pipeline borrows techniques from the mapbox-gl and deck.gl heatmap layers.