Polar numeric value axes
axes.polar configures numeric value axes shared by standalone Charts
and Pivot. It is supported by polarColumn, stackedPolarColumn,
normalizedPolarColumn, radialColumn, radialBar and multiRingRadialBar.
For polar columns and rectangular radial columns, the value axis runs along a radius. For radial bars, the value axis runs along the angle. Categories and series keep their canonical identities and source order in both layouts.
const chart = await createChart({ container, chartType: 'polarColumn', dataset, chartOptions: { startAngle: -90, sweepAngle: 180, innerRadius: 0.25 }, axes: { polar: { value: { scale: 'log', min: 1, max: 1000, tickValues: [1, 10, 100, 1000], unit: 'kg', title: 'Mass', lineColor: '#475569', labelColor: '#334155', }, gridColor: '#cbd5e1', showValues: true, showCategoryLabels: true, showGrid: true, } },});Saved axis options
Section titled “Saved axis options”axes.polar field | Default and contract |
|---|---|
value | Optional ChartPolarValueAxis, the numeric contract below. |
position | Radial axes: 'start' (default), 'end' or a finite angle from -360 to 360 degrees, including fractions. Angular axes: 'outside' (default) or 'inside'. Other orientation/position combinations reject. |
tickSize | 4; finite 0–100 SVG pixels. Zero suppresses short tick marks while retaining labels. |
tickPosition | 'after'; 'before', 'center' or 'after' controls the short tick segment relative to the physical axis line. |
tickLabelPosition | 'after'; 'before', 'center' or 'after' places numeric labels independently of the tick segment. |
disableLine | false; hides only the physical axis line. |
disableTicks | false; hides short numeric tick marks while retaining numeric labels and title. |
disableTickLabel | false; hides numeric text while retaining tick marks and title. |
showValues | true; shows numeric ticks, labels and value-axis title. When false, the physical axis line remains. |
showCategoryLabels | true; retains existing polar category labels independently of numeric labels. Radial-bar labels describe categories with plotted positive entries. |
showGrid | true; draws grid rings or spokes at numeric tick positions. It does not hide radial-bar background tracks or the physical axis line. |
gridColor | Resolved theme grid color; accepts the ordinary validated chart-color syntax. |
With axes.polar omitted, existing geometry and grid behavior remain unchanged.
Setting it to {} enables the shared numeric frame, default value labels and
ratio-based category spacing described in polar geometry.
Removing it restores legacy behavior unless geometry options remain authored.
ChartPolarValueAxis shares the numeric ChartValueAxis contract, excluding
Cartesian position:
scale:'linear','log','symlog'or'sqrt'; linear by default.constant: positive finite symlog transition constant; default1. Only accepted withscale: 'symlog'.min,max: finite bounds, increasing when both are authored; logarithmic bounds must be positive. Bounds use raw numeric units except for normalized polar columns, which use percentage units (0–100automatically).reverse: reverses value projection without changing semantic bound order. This is independent ofchartOptions.polarReverse, which changes angular direction, and of source-array order.tickCount: integer2–1000; bounded numeric tick density.tickValues: up to1000unique finite raw tick positions. Positions outside the committed domain are omitted; source ordering is not changed.tickMinStep,tickMaxStep: positive finite raw step bounds; minimum must not exceed maximum.tickSpacing: positive finite SVG-pixel spacing. Angular axes use arc length; radial axes use the available radial span.unit,tickFormat: numeric tick formatting.tickFormataccepts ordinarynotation('standard','compact'or'scientific') and integerminimumFractionDigits/maximumFractionDigitsfrom0to20, with minimum not exceeding maximum. A supplied format defaults maximum digits to3or the authored minimum, whichever is larger. Omitting the format retains ordinary precision-preserving ticks. These affect axis labels, while tooltips, data labels and CSV retain source formatting.title,titleColor: value-axis title and color. The radial title follows the selected ray; the angular title follows the midpoint of the physical axis arc. Titles use ordinaryaxisTitlelabel customization withaxisId: 'polar'.lineColor,labelColor: physical axis/tick color and numeric-label color. Grid color is controlled separately bygridColor.
Omitting scale and bounds preserves the ordinary zero-to-maximum value domain.
Authoring scale/bounds uses the shared numeric-domain resolver, including its
ordinary automatic padding and degenerate-domain validation. Bounds must also
yield a finite increasing scaled projection; incompatible combinations reject
during preflight. Normalized polar
columns retain a 0–100 domain unless explicitly overridden. Logarithmic bars
start at the inferred/authored positive domain edge. Numeric reversal can make a
bar grow inward, or backward along the angle; raw values remain unchanged.
Axis placement and tick presentation
Section titled “Axis placement and tick presentation”Radial value axes follow the authored sweep’s start or end ray. A numeric
position selects an absolute SVG angle in degrees: zero points right, -90
points up, and 90 points down. It does not rotate bars, category labels or grid
rings. The value-axis title follows the selected ray.
Angular value axes follow either the fitted outer radius ('outside') or the
hole radius ('inside'). Inside tick marks and labels point toward the hole by
default. Tick density and tickSpacing use the physical axis arc length, so an
inside axis may show fewer ticks than the outer axis. Bars retain their same
value projection. Numeric grid spokes still extend over the data region at the
selected tick values. A zero-radius inside axis has no circumference; its
physical line, ticks, numeric labels and title are omitted, while data and grid
remain finite and available.
For a radial start/end axis, the 'after' side points into the open side of that
sweep boundary. Numeric-angle rays follow the start-side normal. For angular
axes, 'after' points outward for an outside axis and into the hole for an inside
axis. 'before' reverses that side; 'center' splits a tick equally across the
line, or centers a label on the line. Labels use their own side setting and an
offset of tickSize + 3 pixels, so hiding tick marks does not shift labels.
Ordinary collision fitting still applies to centered or crowded labels.
showValues: false remains the combined switch for ticks, numeric text and the
title. disableTickLabel hides only numeric text. disableLine is independent
of both; showGrid continues to control only data-aligned numeric grid lines.
Changing physical presentation does not move source bars, change values or
change pointer/keyboard activation, saved models or exports.
// A radial value axis on a custom ray with centered short ticks.await chart.update({ axes: { polar: { ...chart.model.axes?.polar, position: 45, tickSize: 8, tickPosition: 'center', tickLabelPosition: 'before', disableLine: false, disableTicks: false, disableTickLabel: false,} } });ChartPolarAxisPosition and ChartPolarTickPosition are exported public types.
Their Pivot aliases are PivotChartPolarAxisPosition and
PivotChartPolarTickPosition. The placement belongs to axes.polar.position;
Cartesian axes.polar.value.position remains unsupported.
Named numeric polar axes
Section titled “Named numeric polar axes”Define up to 16 additional numeric frames in axes.polar.valueAxes and select
one per source series with seriesOverrides[id].polarAxis. The default
assignment is 'primary', which uses the existing axes.polar.value and its
presentation fields. Named axes work across all six polar/radial-bar types.
const chart = await createChart({ container, dataset, chartType: 'polarColumn', axes: { polar: { position: 'start', value: { min: 0, max: 100, title: 'Units' }, valueAxes: { revenue: { position: 'end', value: { scale: 'log', min: 1, max: 10000, title: 'Revenue', unit: 'USD' }, showGrid: false, tickSize: 6, }, }, } }, seriesOverrides: { revenueSeries: { polarAxis: 'revenue' } },});| New saved field | Contract |
|---|---|
axes.polar.valueAxes | Optional object mapping stable IDs to ChartPolarNumericAxis definitions; empty by default. Each definition accepts value, position, tickSize, tickPosition, tickLabelPosition, disableLine, disableTicks, disableTickLabel, showValues, showGrid and gridColor with the same defaults and validation as the primary axis. It cannot contain valueAxes or showCategoryLabels. |
seriesOverrides[id].polarAxis | Optional numeric-axis ID; defaults to 'primary'. Nonprimary IDs must be declared in valueAxes, including assignments on hidden or currently absent series. Unsupported chart types reject this field. It does not select a Cartesian X/Y axis. |
IDs are nonempty, trimmed strings of at most 128 characters. 'primary',
'__proto__', 'constructor' and 'prototype' cannot be declared as names.
'secondary' has no special meaning here and must be declared like any other
name. Each named definition owns its numeric scale, domain, reversal, unit,
ticks, colors, visibility and physical placement. It does not inherit primary
settings. All frames use the chart’s shared fitted radii, rotation and sweep.
Measured gutters and automatic furniture lanes separate coincident axes. When
text cannot fit, the documented omission policy applies; see polar axis layout
for bounds, collision priority and runtime placement. Distinct authored positions
can provide additional room.
Inferred domains include only positive visible observations assigned to that axis. Stacked totals, overflow divisors and normalized percentages are isolated by axis and category. A large revenue series cannot rescale the primary units series. Normalized polar columns normalize each axis partition to 100 percent; callbacks, tooltips and CSV keep original observations. Stacked polar columns assigned to different axes occupy separate angular slots within each category. Stacked multi-ring radial bars use separate rings for each category/axis partition. Source order determines partition order. Ordinary grouped columns retain their source-series slots. An axis with no assigned visible observations still renders using explicit bounds or the ordinary empty numeric domain; hide its line/grid/values when it should be dormant visually.
Grids for all axes paint beneath data, and numeric labels/titles for all axes
paint above data. Runtime tickFilter and tickLabelFilter receive the new
axisId context field ('primary' or the declared name), with independent
candidate counts and indexes per axis. Use it to apply different selection rules
to different numeric frames. Numeric text customization retains axisId: 'polar'
for the primary axis and uses axisId: 'polar:<name>' for a named axis. SVG
furniture and projected source marks expose data-polar-axis-id with the raw
numeric-axis ID. Named axes retain the same clipping, raw activation, export,
SSR and hydration contracts as the primary frame.
Direct updates are strict: removing a named definition while any series still
references it rejects before committing the new frame. Include reassignment in
the same update to remove it atomically. Named arrays/definitions are owned
snapshots in saved models and queued Pivot updates. The public definition type
is ChartPolarNumericAxis; Pivot exports PivotChartPolarNumericAxis from its
root and charts entry points.
In Pivot’s Axes and scales, enable the polar numeric axis, then use Named polar value axes to add an ID, edit its existing numeric/presentation controls and select it for a series. Remove polar value axis returns every affected series to primary in the same update. Disabling or resetting all polar axes clears polar assignments. Gallery changes between the six compatible types retain named definitions and assignments, pruning incompatible physical positions on every definition when radial/angular roles switch. Changes to unrelated families remove the namespace and polar assignments.
New locale captions are chartOptions.namedPolarAxes, .polarAxisId,
.addPolarAxis and .removePolarAxis; series assignment reuses .seriesAxis.
UI-policy IDs are axes.polar.valueAxes, axes.polar.valueAxes.add,
axes.polar.valueAxes.<id>.<field>,
axes.polar.valueAxes.<id>.value.<numericField>,
axes.polar.valueAxes.<id>.remove and axes.polar.series.<seriesId>.
Runtime tick and label selection
Section titled “Runtime tick and label selection”Use rendererOptions.polarAxis with the default native standalone renderer, or
pass polarAxis to createChartsRenderer / Pivot’s createPivotChartsRenderer.
These application callbacks apply to the configured numeric axes.polar across
all six supported types. They do not enable an omitted numeric axis, and are
inactive on other chart families and in gallery previews.
const polarAxis = { // Keep alternate generated ticks and their numeric grid lines. tickFilter: (tick) => tick.index % 2 === 0, // Further hide the zero label while retaining its tick and grid line. tickLabelFilter: (tick) => tick.value !== 0,};const chart = await createChart({ container, dataset, chartType: 'polarColumn', axes: { polar: { value: { min: 0, max: 100, tickValues: [0, 25, 50, 75, 100], } } }, rendererOptions: { polarAxis },});// Pivot uses exactly the same engine and predicate contract:// renderer: createPivotChartsRenderer({ polarAxis })| Runtime field | Default and behavior |
|---|---|
polarAxis.tickFilter | Omitted: keep every generated numeric candidate. A predicate returning false removes that candidate’s grid line, short tick and numeric label together. |
polarAxis.tickLabelFilter | Omitted: retain the existing label policy. A predicate returning false hides only numeric text; the tick, grid, category labels and axis title remain. |
Each predicate receives one frozen ChartPolarAxisTickContext:
| Context field | Meaning |
|---|---|
axisId | 'primary' or the declared named numeric-axis ID. Tick indexes/counts are independent per axis. |
chartId, chartType | The rendered chart’s identity and type. |
coordinate | 'radius' for polar/rectangular radial columns; 'angle' for radial bars. |
index, count | Zero-based index and total count of the generated, ascending numeric candidates after domain and density filtering, before either predicate. These are tick indexes, never category or series indexes. Removing ticks does not renumber survivors. |
value | Finite raw numeric axis units, including percent for normalized polar columns. null when a stacked tick exceeds the representable raw numeric range. |
scaledValue, tickMultiplier | Finite internal tick value and its common overflow divisor. For representable values, value = scaledValue * tickMultiplier. These let a predicate inspect an overflowing total without receiving Infinity. |
fraction | Projected numeric-domain position from 0 to 1, including numeric-axis reversal. Angular direction and physical axis placement do not change this fraction. |
Candidate generation still obeys the saved scale, domain, tickValues, count,
step and spacing controls. Index order follows ascending numeric values even on
reversed axes. Automatic candidate sets may change on resize; indexes identify
candidates in the current paint, rather than persistent data records. Use value
when a rule must follow a particular numeric value across paints.
tickFilter runs once per candidate per paint. The grid and foreground labels
reuse that decision. tickLabelFilter runs once for each retained label eligible
to paint, using the same context object and original index. It is not called for
labels disabled by showValues, disableTickLabel, previews, zero-radius inside
axes, or the duplicate endpoint of a full angular circle. disableTicks does not
prevent label filtering. Grid visibility, axis-line visibility and title rules
continue to apply independently. Text collision fitting can still omit a label
after the predicate accepts it; returning true does not force overlapping text.
Supplied filters must be functions returning synchronous booleans. Invalid types
or results throw TypeError; application exceptions propagate. Keep callbacks
pure and fast: paints can occur on resize, data/model changes and exports. The
frozen context has no mutable model or dataset references. Selection changes only
axis furniture, never bar geometry, numeric domains, category/series order,
activation payloads, tooltips or CSV observations.
The public types are ChartPolarAxisRendererOptions,
ChartPolarAxisTickPredicate and ChartPolarAxisTickContext. Pivot exports
PivotChartPolarAxisRendererOptions, PivotChartPolarAxisTickPredicate and
PivotChartPolarAxisTickContext from its root and charts entry points.
Runtime filters are not serialized into saved chart models. Supply them again
when restoring a model, rendering server SVG or hydrating it; hydration must use
the same selection to retain the server frame. Normal image/SVG/PDF exports use
the active renderer’s selection. The inspector edits saved numeric options;
application predicates are supplied through the renderer API.
Clipping, stacks and source values
Section titled “Clipping, stacks and source values”Geometry clamps bar intervals to the committed domain. Completely clipped zero-span marks are omitted from pointer/keyboard targets, while cumulative stack bases still advance. Clipped bars retain their original values in activation callbacks, tooltips and CSV. Existing positive-value requirements remain: zero/null cells do not create bars, and this namespace does not enable signed polar data.
Stacked polar columns and stacked multi-ring radial bars infer domains from category totals. Normalized columns use per-category percentages for geometry and axis labels, but their source values remain raw. Hidden profiles and total categories do not contribute to inferred domains. Positive values are scaled before accumulation when raw sums would overflow, preserving finite geometry.
Numeric ticks use the same projection as bars. The shared formatScaledNumber
locale fallback formats unrepresentable raw totals; those labels have no raw
numeric value customization context. Representable numeric labels expose
axisId: 'polar' and their raw tick value, with no Cartesian physical-axis
orientation. A full angular circle keeps one label at the coincident start/end
point. Unlike multi-spoke radar labels, a single radial axis can label its origin.
Numeric labels paint above filled data, including exported SVG. Ordinary density
and collision fitting still apply; authored tick positions do not guarantee that
every text label remains visible.
Pivot and lifecycle
Section titled “Pivot and lifecycle”In Customize → Axes and scales, enable Configure polar value axis and
edit the shared scale, bounds, reversal, unit, title and tick controls. Use
Show polar values, Show polar categories and Show polar value grid
independently. Polar axis position selects start/end/angle for radial values
or outside/inside for angular values. Polar tick size, tick/label side selects
and independent hide switches control the physical axis furniture. Selecting
Polar axis angle begins at zero degrees; edit the numeric field to set a
custom ray. Clearing tick size resumes its default. Cartesian position controls
are omitted. Reset polar axes
removes axes.polar; appearance geometry resets separately. Invalid numeric
field combinations retain the last valid optimistic draft and show an error.
Gallery changes preserve these axes across the six compatible chart types and
remove the namespace for unrelated types. When a gallery change switches between
radial and angular values, it removes an incompatible position while retaining
tick size/sides/visibility and compatible numeric settings. Direct API updates
remain strict. Queued updates own their numeric
arrays before later chart-type transitions execute. Public Pivot aliases are
PivotChartPolarAxes and PivotChartPolarValueAxis.
UI-policy IDs are axes.polar.enabled, axes.polar, axes.polar.value.*,
axes.polar.showValues, axes.polar.showCategoryLabels, axes.polar.showGrid
and axes.polar.reset. Additional IDs are axes.polar.position,
axes.polar.angle (the editor-only numeric angle field), axes.polar.tickSize,
axes.polar.tickPosition, axes.polar.tickLabelPosition, axes.polar.disableLine,
axes.polar.disableTicks and axes.polar.disableTickLabel.
Localize the corresponding chartOptions captions
polarAxes, polarEnable, polarValue, polarReset, polarShowValues,
polarShowCategories and polarShowGrid through localeText. Presentation
captions are polarPosition, polarAngle, polarTickSize, polarTickPosition,
polarTickLabelPosition, polarDisableLine, polarDisableTicks and
polarDisableTickLabel. Position captions use selectValues['polar.start'],
['polar.end'], ['polar.inside'], ['polar.outside']; tick-side captions use
selectValues.before, .center and .after.
Settings persist in models and work with server SVG, in-place hydration, resize and normal image/SVG/PDF export. Parsing and scale preflight reject invalid configurations before committing a new frame. See radar metric axes for the separate category-ID metric-axis contract.
Runtime placement callbacks are available through the measured polar layout contract. Mixed polar composition and value-axis navigation/gestures are outside this contract; radar per-metric axes use the separate guide linked above. The MUI radial-axis reference describes related radial and angular axis behavior; the API above belongs to the shared Charts engine.