Donut
Basic Configuration​
The minimum configuration for the Donut component looks like:
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
import { VisSingleContainer, VisDonut } from '@unovis/react'
function Component(props) {
const data: number[] = props.data
const value = (d: number) => d
return (
<VisSingleContainer data={data}>
<VisDonut value={value}/>
</VisSingleContainer>
)
}
@Component({
templateUrl: 'template.html'
})
export class Component {
@Input data: number[];
value = (d: number) => d
}
<vis-single-container [data]="data">
<vis-donut [value]="value"></vis-donut>
</vis-single-container>
<script lang='ts'>
import { VisSingleContainer, VisDonut } from '@unovis/svelte'
export let data: number[]
const value = (d: number) => d
</script>
<VisSingleContainer {data}>
<VisDonut {value}/>
</VisSingleContainer>
<script setup lang="ts">
import { VisSingleContainer, VisDonut } from '@unovis/vue'
const props = defineProps<{ data: number[] }>()
const value = (d: number) => d
</script>
<template>
<VisSingleContainer :data="data">
<VisDonut :value="value" />
</VisSingleContainer>
</template>
import { VisSingleContainer, VisDonut } from '@unovis/solid'
function Component(props) {
const data: number[] = () => props.data
const value = (d: number) => d
return (
<VisSingleContainer data={data()}>
<VisDonut value={value}/>
</VisSingleContainer>
)
}
import { SingleContainer, Donut } from '@unovis/ts'
import { data } from './data'
const container = new SingleContainer<number>(node, {
component: new Donut<number>({ value: (d: number) => d })
}, data)
Labels​
Donut can have a label and a smaller sub-label in the center. You can provide them by using the centralLabel
and
centralSubLabel
config properties. The sub-label will automatically wrap onto multiple lines (unless you set
the centralSubLabelWrap
property to false
), while the main label is supposed to be short and doesn't have wrapping
implemented.
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisDonut
value={value}
centralLabel="Label"
centralSubLabel="Long sub-label wraps onto the next line"
/>
<vis-donut
[value]="value"
centralLabel="Label"
centralSubLabel="Long sub-label wraps onto the next line"
></vis-donut>
<VisDonut
{value}
centralLabel="Label"
centralSubLabel="Long sub-label wraps onto the next line"
/>
<VisDonut
:value="value"
centralLabel="Label"
centralSubLabel="Long sub-label wraps onto the next line"
/>
<VisDonut
value={value}
centralLabel="Label"
centralSubLabel="Long sub-label wraps onto the next line"
/>
const donut = new Donut<number>({
value,
centralLabel: "Label",
centralSubLabel: "Long sub-label wraps onto the next line"
})
Label Position​
You can adjust the position of both the central label and sub-label using offset properties:
Horizontal Offset​
Use centralLabelOffsetX
to move the labels left or right (negative values move left, positive values move right):
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisDonut
value={value}
centralLabel="Offset Label"
centralSubLabel="Moved horizontally"
centralLabelOffsetX={20}
/>
<vis-donut
[value]="value"
centralLabel="Offset Label"
centralSubLabel="Moved horizontally"
[centralLabelOffsetX]="20"
></vis-donut>
<VisDonut
{value}
centralLabel="Offset Label"
centralSubLabel="Moved horizontally"
centralLabelOffsetX={20}
/>
<VisDonut
:value="value"
centralLabel="Offset Label"
centralSubLabel="Moved horizontally"
:centralLabelOffsetX="20"
/>
<VisDonut
value={value}
centralLabel="Offset Label"
centralSubLabel="Moved horizontally"
centralLabelOffsetX={20}
/>
const donut = new Donut<number>({
value,
centralLabel: "Offset Label",
centralSubLabel: "Moved horizontally",
centralLabelOffsetX: 20
})
Vertical Offset​
Use centralLabelOffsetY
to move the labels up or down (negative values move up, positive values move down):
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisDonut
value={value}
centralLabel="Offset Label"
centralSubLabel="Moved vertically"
centralLabelOffsetY={-15}
/>
<vis-donut
[value]="value"
centralLabel="Offset Label"
centralSubLabel="Moved vertically"
[centralLabelOffsetY]="-15"
></vis-donut>
<VisDonut
{value}
centralLabel="Offset Label"
centralSubLabel="Moved vertically"
centralLabelOffsetY={-15}
/>
<VisDonut
:value="value"
centralLabel="Offset Label"
centralSubLabel="Moved vertically"
:centralLabelOffsetY="-15"
/>
<VisDonut
value={value}
centralLabel="Offset Label"
centralSubLabel="Moved vertically"
centralLabelOffsetY={-15}
/>
const donut = new Donut<number>({
value,
centralLabel: "Offset Label",
centralSubLabel: "Moved vertically",
centralLabelOffsetY: -15
})
You can combine both offsets to position the labels exactly where you need them.
Angle Range​
By default, a Donut will populate values in the angle range [0, 2Ï€]
. You can adjust your Donut's angleRange
property to a [a,b]
of type [number, number]
where a[0] = the starting position and a[1] = the ending position (in radians). A common example might be when you want an incomplete/semi circle:
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisDonut value={value} angleRange={[1,3.141592653589793]}/>
<vis-donut
[value]="value"
[angleRange]="[1,3.141592653589793]"
></vis-donut>
<VisDonut {value} angleRange={[1,3.141592653589793]}/>
<VisDonut :value="value" :angleRange="[1,3.141592653589793]" />
<VisDonut value={value} angleRange={[1,3.141592653589793]}/>
const donut = new Donut<number>({ value, angleRange: [1,3.141592653589793] })
Half Donut Charts​
For convenience, Unovis provides preset angle ranges to create half donut charts in different orientations. You can import these constants from @unovis/ts
:
import {
DONUT_HALF_ANGLE_RANGE_TOP,
DONUT_HALF_ANGLE_RANGE_RIGHT,
DONUT_HALF_ANGLE_RANGE_BOTTOM,
DONUT_HALF_ANGLE_RANGE_LEFT
} from '@unovis/ts'
Sorting​
By default, each segment is placed in order of appearance within your data
array, from
To change this, provide a sorting function to the sortFunction
property. The following example displays the segments in descending order:
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
import { VisSingleContainer, VisDonut } from '@unovis/react'
function Component(props) {
const data: number[] = props.data
const value = (d: number) => d
const sortFunction = (a, b) => a - b
return (
<VisSingleContainer data={data}>
<VisDonut value={value} sortFunction={sortFunction}/>
</VisSingleContainer>
)
}
@Component({
templateUrl: 'template.html'
})
export class Component {
@Input data: number[];
value = (d: number) => d
sortFunction = (a, b) => a - b
}
<vis-single-container [data]="data">
<vis-donut [value]="value" [sortFunction]="sortFunction"></vis-donut>
</vis-single-container>
<script lang='ts'>
import { VisSingleContainer, VisDonut } from '@unovis/svelte'
export let data: number[]
const value = (d: number) => d
const sortFunction = (a, b) => a - b
</script>
<VisSingleContainer {data}>
<VisDonut {value} {sortFunction}/>
</VisSingleContainer>
<script setup lang="ts">
import { VisSingleContainer, VisDonut } from '@unovis/vue'
const props = defineProps<{ data: number[] }>()
const value = (d: number) => d
const sortFunction = (a, b) => a - b
</script>
<template>
<VisSingleContainer :data="data">
<VisDonut :value="value" :sortFunction="sortFunction" />
</VisSingleContainer>
</template>
import { VisSingleContainer, VisDonut } from '@unovis/solid'
function Component(props) {
const data: number[] = () => props.data
const value = (d: number) => d
const sortFunction = (a, b) => a - b
return (
<VisSingleContainer data={data()}>
<VisDonut value={value} sortFunction={sortFunction}/>
</VisSingleContainer>
)
}
import { SingleContainer, Donut } from '@unovis/ts'
import { data } from './data'
const container = new SingleContainer<number>(node, {
component: new Donut<number>({
value: (d: number) => d,
sortFunction: (a, b) => a - b
})
}, data)
Size​
You can change the size of your Donut with the following properties:
Radius​
radius
defines the outer/overall radius:
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisDonut radius={50} value={value}/>
<vis-donut [radius]="50" [value]="value"></vis-donut>
<VisDonut radius={50} {value}/>
<VisDonut :radius="50" :value="value" />
<VisDonut radius={50} value={value}/>
const donut = new Donut<number>({ radius: 50, value })
Arc Width​
arcWidth
defines the width of the circle's outer ring in pixels.
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisDonut arcWidth={50} value={value}/>
<vis-donut [arcWidth]="50" [value]="value"></vis-donut>
<VisDonut arcWidth={50} {value}/>
<VisDonut :arcWidth="50" :value="value" />
<VisDonut arcWidth={50} value={value}/>
const donut = new Donut<number>({ arcWidth: 50, value })
For the appearance of a traditional pie chart, set Donut's arcWidth
to 0
.
Segment Appearance​
Custom Color​
Customize the colors for each segment with a colorAccessor
function:
- 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) => ['red', 'orange', 'blue', 'green'][i]
return (
<VisDonut value={value} color={color}/>
)
}
@Component({
template: '<vis-donut [value]="value" [color]="color"></vis-donut>'
})
export class Component {
@Input data: number[];
value = (d: number) => d
color = (d: number, i: number) => ['red', 'orange', 'blue', 'green'][i]
}
<script lang='ts'>
import { VisSingleContainer, VisDonut } from '@unovis/svelte'
export let data: number[]
const value = (d: number) => d
const color = (d: number, i: number) => ['red', 'orange', 'blue', 'green'][i]
</script>
<VisDonut {value} {color}/>
<script setup lang="ts">
import { VisSingleContainer, VisDonut } from '@unovis/vue'
const props = defineProps<{ data: number[] }>()
const value = (d: number) => d
const color = (d: number, i: number) => ['red', 'orange', 'blue', 'green'][i]
</script>
<template>
<VisDonut :value="value" :color="color" />
</template>
function Component(props) {
const data: number[] = () => props.data
const value = (d: number) => d
const color = (d: number, i: number) => ['red', 'orange', 'blue', 'green'][i]
return (
<VisDonut value={value} color={color}/>
)
}
const donut = new Donut<number>({
value: (d: number) => d,
color: (d: number, i: number) => ['red', 'orange', 'blue', 'green'][i]
})
Corner Radius​
Providing a value to the cornerRadius
property adds rounded corners to your Donut's segments proportional to the Donut's arcWidth
.
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisDonut cornerRadius={5} value={value}/>
<vis-donut [cornerRadius]="5" [value]="value"></vis-donut>
<VisDonut cornerRadius={5} {value}/>
<VisDonut :cornerRadius="5" :value="value" />
<VisDonut cornerRadius={5} value={value}/>
const donut = new Donut<number>({ cornerRadius: 5, value })
Pad angle​
Pad each segment with the padAngle
property.
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisDonut value={value} padAngle={0.1}/>
<vis-donut [value]="value" [padAngle]="0.1"></vis-donut>
<VisDonut {value} padAngle={0.1}/>
<VisDonut :value="value" :padAngle="0.1" />
<VisDonut value={value} padAngle={0.1}/>
const donut = new Donut<number>({ value, padAngle: 0.1 })
Empty Segments​
When segments are empty (i.e. when their values are 0), you may still want them displayed in your Donut as thin slices.
To do this, set showEmptySegments
to true
:
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisDonut showEmptySegments={true} value={value} padAngle={0.03}/>
<vis-donut
[showEmptySegments]="true"
[value]="value"
[padAngle]="0.03"
></vis-donut>
<VisDonut showEmptySegments={true} {value} padAngle={0.03}/>
<VisDonut :showEmptySegments="true" :value="value" :padAngle="0.03" />
<VisDonut showEmptySegments={true} value={value} padAngle={0.03}/>
const donut = new Donut<number>({ showEmptySegments: true, value, padAngle: 0.03 })
Customizing empty segment size​
When showEmptySegments
is enabled, the default size for empty segments is 0.5 * π / 180
radians. You can tweak this to your
liking with the emptySegmentAngle
property which accepts a number
in radians.
For example, setting emptySegmentAngle
to Math.PI / 12
looks like:
Note that this property will have no effect if showEmptySegments
is false
.
Background​
By default, Donut has a background underneath the segments, which is useful when your chart is empty. You can turn it off by setting
showBackground
to false
.
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisDonut
showBackground={true}
value={value}
angleRange={[-1.5707963267948966,1.5707963267948966]}
/>
<vis-donut
[showBackground]="true"
[value]="value"
[angleRange]="[-1.5707963267948966,1.5707963267948966]"
></vis-donut>
<VisDonut
showBackground={true}
{value}
angleRange={[-1.5707963267948966,1.5707963267948966]}
/>
<VisDonut
:showBackground="true"
:value="value"
:angleRange="[-1.5707963267948966,1.5707963267948966]"
/>
<VisDonut
showBackground={true}
value={value}
angleRange={[-1.5707963267948966,1.5707963267948966]}
/>
const donut = new Donut<number>({
showBackground: true,
value,
angleRange: [-1.5707963267948966,1.5707963267948966]
})
Also, you can change the angular range of the background by providing a [number, number]
value (in radians) to backgroundAngleRange
.
By default, the background angular range will be the same as angleRange
.
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisDonut
value={value}
showBackground={true}
angleRange={[0,1.0471975511965976]}
backgroundAngleRange={[0,6.283185307179586]}
/>
<vis-donut
[value]="value"
[showBackground]="true"
[angleRange]="[0,1.0471975511965976]"
[backgroundAngleRange]="[0,6.283185307179586]"
></vis-donut>
<VisDonut
{value}
showBackground={true}
angleRange={[0,1.0471975511965976]}
backgroundAngleRange={[0,6.283185307179586]}
/>
<VisDonut
:value="value"
:showBackground="true"
:angleRange="[0,1.0471975511965976]"
:backgroundAngleRange="[0,6.283185307179586]"
/>
<VisDonut
value={value}
showBackground={true}
angleRange={[0,1.0471975511965976]}
backgroundAngleRange={[0,6.283185307179586]}
/>
const donut = new Donut<number>({
value,
showBackground: true,
angleRange: [0,1.0471975511965976],
backgroundAngleRange: [0,6.283185307179586]
})
The color of the background can be changed via the --vis-donut-background-color
and
--vis-dark-donut-background-color
CSS variables.
Events​
The following selectors are available for events:
import { Donut } from '@unovis/ts'
...
events = {
[Donut.selectors.segment]: { },
[Donut.selectors.background]: { },
[Donut.selectors.centralLabel]: { },
[Donut.selectors.centralSubLabel]: { },
}
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisDonut value={value} events={events}/>
<vis-donut [value]="value" [events]="events"></vis-donut>
<VisDonut {value} {events}/>
<VisDonut :value="value" :events="events" />
<VisDonut value={value} events={events}/>
const donut = new Donut<number>({ value, events })
CSS Variables​
All supported CSS variables and their default values
--vis-donut-central-label-font-size: 16px;
--vis-donut-central-label-text-color: #5b5f6d;
--vis-donut-central-label-font-family
--vis-donut-central-label-font-weight: 600;
--vis-donut-central-sub-label-font-size: 12px;
--vis-donut-central-sub-label-text-color: #5b5f6d;
--vis-donut-central-sub-label-font-family
--vis-donut-central-sub-label-font-weight: 500;
--vis-donut-background-color: #E7E9F3;
--vis-dark-donut-central-label-text-color: #C2BECE;
--vis-dark-donut-central-sub-label-text-color: #C2BECE;
--vis-dark-donut-background-color: #18160C;
Component Props​
Name | Type | Description |
---|---|---|
* required property |