RadialBar
Basic Configuration
The Radial Bar chart draws one circular track per data record and fills each track with a colored bar proportional to its value. The minimum configuration looks like:
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
import { VisSingleContainer, VisRadialBar } from '@unovis/react'
function Component(props) {
const data: number[] = props.data
const value = (d: number) => d
return (
<VisSingleContainer data={data}>
<VisRadialBar value={value}/>
</VisSingleContainer>
)
}
@Component({
templateUrl: 'template.html'
})
export class Component {
@Input data: number[];
value = (d: number) => d
}
<vis-single-container [data]="data">
<vis-radial-bar [value]="value"></vis-radial-bar>
</vis-single-container>
<script lang='ts'>
import { VisSingleContainer, VisRadialBar } from '@unovis/svelte'
export let data: number[]
const value = (d: number) => d
</script>
<VisSingleContainer {data}>
<VisRadialBar {value}/>
</VisSingleContainer>
<script setup lang="ts">
import { VisSingleContainer, VisRadialBar } from '@unovis/vue'
const props = defineProps<{ data: number[] }>()
const value = (d: number) => d
</script>
<template>
<VisSingleContainer :data="data">
<VisRadialBar :value="value" />
</VisSingleContainer>
</template>
import { VisSingleContainer, VisRadialBar } from '@unovis/solid'
function Component(props) {
const data: number[] = () => props.data
const value = (d: number) => d
return (
<VisSingleContainer data={data()}>
<VisRadialBar value={value}/>
</VisSingleContainer>
)
}
import { SingleContainer, RadialBar } from '@unovis/ts'
import { data } from './data'
const container = new SingleContainer<number>(node, {
component: new RadialBar<number>({ value: (d: number) => d })
}, data)
Max Value
Each bar fills value / maxValue * (angleRange[1] - angleRange[0]). When maxValue is undefined (the default), the maximum is derived from the data.
Pass a number to use one max for all rings, or a per-datum accessor when each ring should scale against its own target:
// Auto-derive max from data (default)
maxValue={undefined}
// Single shared max
maxValue={100}
// Per-ring target
maxValue={d => d.target}
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisRadialBar value={value} maxValue={1}/>
<vis-radial-bar [value]="value" [maxValue]="1"></vis-radial-bar>
<VisRadialBar {value} maxValue={1}/>
<VisRadialBar :value="value" :maxValue="1" />
<VisRadialBar value={value} maxValue={1}/>
const radialBar = new RadialBar<number>({ value, maxValue: 1 })
Labels
You can place text in the center of the chart with the centralLabel and centralSubLabel properties — the same
API as the Donut chart. The sub-label wraps onto multiple lines automatically (toggle with
centralSubLabelWrap).
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisRadialBar
value={value}
centralLabel="8"
centralSubLabel="open · in progress"
/>
<vis-radial-bar
[value]="value"
centralLabel="8"
centralSubLabel="open · in progress"
></vis-radial-bar>
<VisRadialBar
{value}
centralLabel="8"
centralSubLabel="open · in progress"
/>
<VisRadialBar
:value="value"
centralLabel="8"
centralSubLabel="open · in progress"
/>
<VisRadialBar
value={value}
centralLabel="8"
centralSubLabel="open · in progress"
/>
const radialBar = new RadialBar<number>({
value,
centralLabel: "8",
centralSubLabel: "open · in progress"
})
Label Position
The labels are centered as a single block — the geometric midpoint of the top label plus the (potentially wrapped) sub-label is placed at the chart center, regardless of the font-size ratio between the two.
Use centralLabelOffsetX / centralLabelOffsetY to nudge the block (negative values move up/left, positive move down/right):
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisRadialBar
value={value}
centralLabel="Offset"
centralSubLabel="Moved up"
centralLabelOffsetY={-15}
/>
<vis-radial-bar
[value]="value"
centralLabel="Offset"
centralSubLabel="Moved up"
[centralLabelOffsetY]="-15"
></vis-radial-bar>
<VisRadialBar
{value}
centralLabel="Offset"
centralSubLabel="Moved up"
centralLabelOffsetY={-15}
/>
<VisRadialBar
:value="value"
centralLabel="Offset"
centralSubLabel="Moved up"
:centralLabelOffsetY="-15"
/>
<VisRadialBar
value={value}
centralLabel="Offset"
centralSubLabel="Moved up"
centralLabelOffsetY={-15}
/>
const radialBar = new RadialBar<number>({
value,
centralLabel: "Offset",
centralSubLabel: "Moved up",
centralLabelOffsetY: -15
})
Angle Range
By default a Radial Bar spans the full [0, 2π] circle. Pass a [start, end] tuple in radians to render a
partial range — useful for semicircular or gauge-style charts.
For partial arcs the chart's origin lands on the bbox edge of the visible arc, so you may want to combine centralLabelOffsetY with the --vis-radial-bar-central-label-text-anchor / --vis-radial-bar-central-sub-label-text-anchor CSS variables (start / middle / end) to align the labels toward the side the arc opens to.
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisRadialBar
value={value}
angleRange={[-1.5707963267948966,1.5707963267948966]}
centralLabel="Gauge"
centralLabelOffsetY={-15}
/>
<vis-radial-bar
[value]="value"
[angleRange]="[-1.5707963267948966,1.5707963267948966]"
centralLabel="Gauge"
[centralLabelOffsetY]="-15"
></vis-radial-bar>
<VisRadialBar
{value}
angleRange={[-1.5707963267948966,1.5707963267948966]}
centralLabel="Gauge"
centralLabelOffsetY={-15}
/>
<VisRadialBar
:value="value"
:angleRange="[-1.5707963267948966,1.5707963267948966]"
centralLabel="Gauge"
:centralLabelOffsetY="-15"
/>
<VisRadialBar
value={value}
angleRange={[-1.5707963267948966,1.5707963267948966]}
centralLabel="Gauge"
centralLabelOffsetY={-15}
/>
const radialBar = new RadialBar<number>({
value,
angleRange: [-1.5707963267948966,1.5707963267948966],
centralLabel: "Gauge",
centralLabelOffsetY: -15
})
Minimum Bar Angle
Bars representing very small values can become too short to notice. barMinAngle sets the minimum angular extent
of a bar in radians, so that such bars remain visible. It defaults to 0.01, which is about one pixel wide on a
ring of a 100 pixel radius — increase it to make small values more prominent, or set it to 0 to disable.
The value is clamped to the length of angleRange.
0 counts as a value, so zero bars are rendered with the minimum angle too. Missing data is different: when the
value accessor returns null or undefined, the bar is not rendered at all and only its background track remains.
In the example below the rings are, from the outside in: a tiny value, a regular value, 0, and null:
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisRadialBar value={value} maxValue={1} barMinAngle={0.15}/>
<vis-radial-bar
[value]="value"
[maxValue]="1"
[barMinAngle]="0.15"
></vis-radial-bar>
<VisRadialBar {value} maxValue={1} barMinAngle={0.15}/>
<VisRadialBar :value="value" :maxValue="1" :barMinAngle="0.15" />
<VisRadialBar value={value} maxValue={1} barMinAngle={0.15}/>
const radialBar = new RadialBar<number>({ value, maxValue: 1, barMinAngle: 0.15 })
Stacking Order
By default data[0] is the outermost ring and subsequent data render inward. Set reverseOrder to true
to flip the order:
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisRadialBar value={value} reverseOrder={true}/>
<vis-radial-bar [value]="value" [reverseOrder]="true"></vis-radial-bar>
<VisRadialBar {value} reverseOrder={true}/>
<VisRadialBar :value="value" :reverseOrder="true" />
<VisRadialBar value={value} reverseOrder={true}/>
const radialBar = new RadialBar<number>({ value, reverseOrder: true })
Sorting
Provide a sortFunction to control the ring order independently of how the data was provided:
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisRadialBar value={value} sortFunction={sortFunction}/>
<vis-radial-bar
[value]="value"
[sortFunction]="sortFunction"
></vis-radial-bar>
<VisRadialBar {value} {sortFunction}/>
<VisRadialBar :value="value" :sortFunction="sortFunction" />
<VisRadialBar value={value} sortFunction={sortFunction}/>
const radialBar = new RadialBar<number>({ value, sortFunction })
Size
Radius
radius sets the outermost ring's outer radius (in pixels). When undefined, the chart fills the available space.
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisRadialBar value={value} radius={80}/>
<vis-radial-bar [value]="value" [radius]="80"></vis-radial-bar>
<VisRadialBar {value} radius={80}/>
<VisRadialBar :value="value" :radius="80" />
<VisRadialBar value={value} radius={80}/>
const radialBar = new RadialBar<number>({ value, radius: 80 })
Track Width
trackWidth is the width of each ring in pixels.
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisRadialBar value={value} trackWidth={16}/>
<vis-radial-bar [value]="value" [trackWidth]="16"></vis-radial-bar>
<VisRadialBar {value} trackWidth={16}/>
<VisRadialBar :value="value" :trackWidth="16" />
<VisRadialBar value={value} trackWidth={16}/>
const radialBar = new RadialBar<number>({ value, trackWidth: 16 })
Track Padding
trackPadding is the gap between rings in pixels.
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisRadialBar value={value} trackPadding={4}/>
<vis-radial-bar [value]="value" [trackPadding]="4"></vis-radial-bar>
<VisRadialBar {value} trackPadding={4}/>
<VisRadialBar :value="value" :trackPadding="4" />
<VisRadialBar value={value} trackPadding={4}/>
const radialBar = new RadialBar<number>({ value, trackPadding: 4 })
Bar Appearance
Custom Color
Customize the colors with a color accessor:
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
function Component(props) {
const data: number[] = props.data
const value = (d: number) => d
const color = (d: number, i: number) => ['#4D8CFD', '#F4B83E', '#A6CC74'][i]
return (
<VisRadialBar value={value} color={color}/>
)
}
@Component({
template: '<vis-radial-bar [value]="value" [color]="color"></vis-radial-bar>'
})
export class Component {
@Input data: number[];
value = (d: number) => d
color = (d: number, i: number) => ['#4D8CFD', '#F4B83E', '#A6CC74'][i]
}
<script lang='ts'>
import { VisSingleContainer, VisRadialBar } from '@unovis/svelte'
export let data: number[]
const value = (d: number) => d
const color = (d: number, i: number) => ['#4D8CFD', '#F4B83E', '#A6CC74'][i]
</script>
<VisRadialBar {value} {color}/>
<script setup lang="ts">
import { VisSingleContainer, VisRadialBar } from '@unovis/vue'
const props = defineProps<{ data: number[] }>()
const value = (d: number) => d
const color = (d: number, i: number) => ['#4D8CFD', '#F4B83E', '#A6CC74'][i]
</script>
<template>
<VisRadialBar :value="value" :color="color" />
</template>
function Component(props) {
const data: number[] = () => props.data
const value = (d: number) => d
const color = (d: number, i: number) => ['#4D8CFD', '#F4B83E', '#A6CC74'][i]
return (
<VisRadialBar value={value} color={color}/>
)
}
const radialBar = new RadialBar<number>({
value: (d: number) => d,
color: (d: number, i: number) => ['#4D8CFD', '#F4B83E', '#A6CC74'][i]
})
Corner Radius
Rounded caps are off by default. Increase cornerRadius for activity-ring style rounded ends:
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisRadialBar value={value} trackWidth={20} cornerRadius={10}/>
<vis-radial-bar
[value]="value"
[trackWidth]="20"
[cornerRadius]="10"
></vis-radial-bar>
<VisRadialBar {value} trackWidth={20} cornerRadius={10}/>
<VisRadialBar :value="value" :trackWidth="20" :cornerRadius="10" />
<VisRadialBar value={value} trackWidth={20} cornerRadius={10}/>
const radialBar = new RadialBar<number>({ value, trackWidth: 20, cornerRadius: 10 })
Background
By default each ring has a faded background that shows the 100% track. Disable globally with showBackground={false},
or override the angular range with backgroundAngleRange.
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisRadialBar value={value} showBackground={true}/>
<vis-radial-bar
[value]="value"
[showBackground]="true"
></vis-radial-bar>
<VisRadialBar {value} showBackground={true}/>
<VisRadialBar :value="value" :showBackground="true" />
<VisRadialBar value={value} showBackground={true}/>
const radialBar = new RadialBar<number>({ value, showBackground: true })
The background color is configured via the --vis-radial-bar-background-color and
--vis-dark-radial-bar-background-color CSS variables.
Events
The following selectors are available for events:
import { RadialBar } from '@unovis/ts'
...
events = {
[RadialBar.selectors.bar]: { },
[RadialBar.selectors.background]: { },
[RadialBar.selectors.centralLabel]: { },
[RadialBar.selectors.centralSubLabel]: { },
}
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisRadialBar value={value} events={events}/>
<vis-radial-bar [value]="value" [events]="events"></vis-radial-bar>
<VisRadialBar {value} {events}/>
<VisRadialBar :value="value" :events="events" />
<VisRadialBar value={value} events={events}/>
const radialBar = new RadialBar<number>({ value, events })
CSS Variables
All supported CSS variables and their default values
--vis-radial-bar-central-label-font-size: 24px;
--vis-radial-bar-central-label-text-color: #5b5f6d;
--vis-radial-bar-central-label-font-family: undefined;
--vis-radial-bar-central-label-font-weight: 600;
--vis-radial-bar-central-label-text-anchor: middle;
--vis-radial-bar-central-sub-label-font-size: 12px;
--vis-radial-bar-central-sub-label-text-color: #5b5f6d;
--vis-radial-bar-central-sub-label-font-family: undefined;
--vis-radial-bar-central-sub-label-font-weight: 500;
--vis-radial-bar-central-sub-label-text-anchor: middle;
--vis-radial-bar-background-color: #E7E9F3;
--vis-radial-bar-bar-stroke-width: 0;
--vis-radial-bar-bar-stroke-color: undefined;
--vis-dark-radial-bar-central-label-text-color: #C2BECE;
--vis-dark-radial-bar-central-sub-label-text-color: #C2BECE;
--vis-dark-radial-bar-background-color: #444444;
Component Props
| Name | Type | Description |
|---|---|---|
| * required property |