Mark Reference
- Line and Area Marks
- Difference Marks
- Linear Regression Marks
- Bar and Rect Marks
- Box Marks
- Dot and Hexagon Marks
- Dodge Layouts
- Waffle Marks
- Ridgeline Marks
- Violin Marks
- Focus Guide Marks
- Treemap Mark
- Sunburst Mark
- Sankey Diagram Mark
- Hexbin Mark
- Contour Mark
- Density Contour Mark
- Delaunay Link Mark
- Voronoi Mark
- Rules, Links, Arrows, Vectors, and Ticks
- Text, Frame, and Facet
- Geo Shape Mark
- Polar Marks
Density Contour Mark
densityContour estimates a two-dimensional density field after the chart resolves its positional scales and inner bounds. Import it from the optional spatial subpath; it is not included in the root or universal barrel.
import { densityContour } from '@tanstack/charts/spatial/density'
const mark = densityContour(penguins, {
x: 'billLength',
y: 'billDepth',
bandwidth: 18,
thresholds: [0.0004, 0.0008, 0.0012, 0.0016, 0.002, 0.0024],
fill: '#2563eb',
fillOpacity: 0.16,
stroke: '#1e3a8a',
})function densityContour<TDatum>(
source: Iterable<TDatum>,
options: DensityContourOptions<TDatum>,
): ChartMark<never, never, never, InferredX, InferredY>The mark contributes x/y and derived color domains but intentionally emits no ChartPoint interaction candidates.
Options#
| Option | Type | Default | Meaning |
|---|---|---|---|
| x | Channel<TDatum, ChartValue?> | Required | Source horizontal observation |
| y | Channel<TDatum, ChartValue?> | Required | Source vertical observation |
| z | Channel<TDatum, ChartKey?> | null group | Independent density-estimator group |
| weight | Channel<TDatum, number?> | 1 | Observation weight |
| bandwidth | number | 20 | Gaussian-kernel bandwidth in final CSS pixels |
| cellSize | number | 4 | Density-grid cell size in final CSS pixels |
| thresholds | number | Iterable<number> | 20 | Approximate shared level count or exact density levels |
| color | Channel<DensityContourDatum, ChartKey?> | group | Derived value sent to the color scale; never an estimator group |
| fill | VisualChannel<DensityContourDatum, string> | Resolved color | Contour fill |
| stroke | VisualChannel<DensityContourDatum, string> | None | Contour stroke |
| fillOpacity, strokeOpacity, and strokeWidth | number | Renderer default | Contour presentation |
| strokeDasharray | string | None | Contour stroke dash pattern |
| opacity | number | Renderer default | Whole-contour opacity |
| id | string | Layer-derived | Stable mark ID |
| motion | ChartMarkMotionOptions<never>['motion'] | None | Contour enter, update, and exit motion |
bandwidth must be nonnegative and finite. cellSize must be at least one; the D3 estimator rounds it down to a supported power of two. A numeric threshold count must be a positive integer. Exact thresholds use weighted observations per CSS pixel squared, the native unit of d3-contour.
Resolved estimation#
Complete x/y pairs establish the positional domains. The mark maps them through the final scales, estimates inside the final plot rectangle, and clips the output there. Resizing or changing margins can change the contours even when the semantic domains are fixed. Scale inversion is not required.
An explicit z runs one estimator per group. Numeric threshold counts resolve to one shared set of levels using the maximum across every group, so levels remain comparable. color affects presentation only and never partitions the estimator.
Missing or unmappable x/y pairs and zero or nonfinite weights contribute nothing. Finite signed weights are passed to the estimator. Every rendered DensityContourDatum<TDatum> contains:
- density, the native threshold value;
- group, the explicit z value or null;
- source, the contributing input rows for that estimator group; and
- sourceIndexes, their original input indexes.
Presentation accessors receive this derived datum and the complete rendered contour array.
Geometry and interaction#
Each level is one structured scene area containing all disconnected polygons and holes. SVG, Canvas, React Native SVG, hit geometry, gradients, and clipping consume the same rings; the mark does not author SVG path strings or depend on d3-geo.
A contour can have several disconnected regions, and an aggregate centroid can fall outside all of them. The mark therefore does not manufacture a centroid focus target or tooltip datum. Layer an interactive source mark when individual observations should own focus and tooltips.