Treemap
Treemap is a visualization component that displays hierarchical data using nested rectangles. Each rectangle's area corresponds to a quantitative value, making it easy to compare different parts of a hierarchy at a glance.
Data​
Treemap expects an array of generic data records, the properties of which will be used to define the layers. Each layer will contain tiles that represent their corresponding quantity in the data array.
For the following examples, assume data is of type Datum[]
.
type Datum = {
group: string;
subgroup: string;
value: number;
};
Defining Layers​
The layers
property accepts an array of string accessor functions based on the Datum
provided.
The first accessor will define the top level of the hierarchy, the second will provide the next level, and so on.
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
import { VisSingleContainer, VisTreemap } from '@unovis/react'
function Component(props) {
const data: Datum[] = props.data
const layers = [(d: Datum) => d.group, (d: Datum) => d.subgroup]
return (
<VisSingleContainer data={data}>
<VisTreemap layers={layers}/>
</VisSingleContainer>
)
}
@Component({
templateUrl: 'template.html'
})
export class Component {
@Input data: Datum[];
layers = [(d: Datum) => d.group, (d: Datum) => d.subgroup]
}
<vis-single-container [data]="data">
<vis-treemap [layers]="layers"></vis-treemap>
</vis-single-container>
<script lang='ts'>
import { VisSingleContainer, VisTreemap } from '@unovis/svelte'
export let data: Datum[]
const layers = [(d: Datum) => d.group, (d: Datum) => d.subgroup]
</script>
<VisSingleContainer {data}>
<VisTreemap {layers}/>
</VisSingleContainer>
<script setup lang="ts">
import { VisSingleContainer, VisTreemap } from '@unovis/vue'
const props = defineProps<{ data: Datum[] }>()
const layers = [(d: Datum) => d.group, (d: Datum) => d.subgroup]
</script>
<template>
<VisSingleContainer :data="data">
<VisTreemap :layers="layers" />
</VisSingleContainer>
</template>
import { VisSingleContainer, VisTreemap } from '@unovis/solid'
function Component(props) {
const data: Datum[] = () => props.data
const layers = [(d: Datum) => d.group, (d: Datum) => d.subgroup]
return (
<VisSingleContainer data={data()}>
<VisTreemap layers={layers}/>
</VisSingleContainer>
)
}
import { SingleContainer, Treemap } from '@unovis/ts'
import { data, Datum } from './data'
const container = new SingleContainer<Datum>(node, {
component: new Treemap<Datum>({
layers: [(d: Datum) => d.group, (d: Datum) => d.subgroup]
})
}, data)
Tile Values​
By default, tile sizes are assigned based on the number of occurrences within the data array.
To override this behavior, you can provide your own value
accessor function.
value = (d: Datum) => d.value
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
import { VisSingleContainer, VisTreemap } from '@unovis/react'
function Component(props) {
const data: Datum[] = props.data
const layers = [(d: Datum) => d.group, (d: Datum) => d.subgroup]
const value = (d: Datum) => d.value
return (
<VisSingleContainer data={data}>
<VisTreemap layers={layers} value={value}/>
</VisSingleContainer>
)
}
@Component({
templateUrl: 'template.html'
})
export class Component {
@Input data: Datum[];
layers = [(d: Datum) => d.group, (d: Datum) => d.subgroup]
value = (d: Datum) => d.value
}
<vis-single-container [data]="data">
<vis-treemap [layers]="layers" [value]="value"></vis-treemap>
</vis-single-container>
<script lang='ts'>
import { VisSingleContainer, VisTreemap } from '@unovis/svelte'
export let data: Datum[]
const layers = [(d: Datum) => d.group, (d: Datum) => d.subgroup]
const value = (d: Datum) => d.value
</script>
<VisSingleContainer {data}>
<VisTreemap {layers} {value}/>
</VisSingleContainer>
<script setup lang="ts">
import { VisSingleContainer, VisTreemap } from '@unovis/vue'
const props = defineProps<{ data: Datum[] }>()
const layers = [(d: Datum) => d.group, (d: Datum) => d.subgroup]
const value = (d: Datum) => d.value
</script>
<template>
<VisSingleContainer :data="data">
<VisTreemap :layers="layers" :value="value" />
</VisSingleContainer>
</template>
import { VisSingleContainer, VisTreemap } from '@unovis/solid'
function Component(props) {
const data: Datum[] = () => props.data
const layers = [(d: Datum) => d.group, (d: Datum) => d.subgroup]
const value = (d: Datum) => d.value
return (
<VisSingleContainer data={data()}>
<VisTreemap layers={layers} value={value}/>
</VisSingleContainer>
)
}
import { SingleContainer, Treemap } from '@unovis/ts'
import { data, Datum } from './data'
const container = new SingleContainer<Datum>(node, {
component: new Treemap<Datum>({
layers: [(d: Datum) => d.group, (d: Datum) => d.subgroup],
value: (d: Datum) => d.value
})
}, data)
Tile Appearance​
Tile Color​
You can customize the colors for each tile using the tileColor
property:
tileColor = (d: TreemapNode<Datum>) => groupColors[d.data.key]
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisTreemap layers={layers} tileColor={tileColor}/>
<vis-treemap [layers]="layers" [tileColor]="tileColor"></vis-treemap>
<VisTreemap {layers} {tileColor}/>
<VisTreemap :layers="layers" :tileColor="tileColor" />
<VisTreemap layers={layers} tileColor={tileColor}/>
const treemap = new Treemap<Datum>({ layers, tileColor })
Tile Padding​
Control the spacing between tiles using the tilePadding
property, which accepts a numeric value in pixels:
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisTreemap layers={layers} tilePadding={4}/>
<vis-treemap [layers]="layers" [tilePadding]="4"></vis-treemap>
<VisTreemap {layers} tilePadding={4}/>
<VisTreemap :layers="layers" :tilePadding="4" />
<VisTreemap layers={layers} tilePadding={4}/>
const treemap = new Treemap<Datum>({ layers, tilePadding: 4 })
Tile Border Radius​
Add rounded corners to your tiles with the tileBorderRadius
property:
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisTreemap layers={layers} tileBorderRadius={8}/>
<vis-treemap [layers]="layers" [tileBorderRadius]="8"></vis-treemap>
<VisTreemap {layers} tileBorderRadius={8}/>
<VisTreemap :layers="layers" :tileBorderRadius="8" />
<VisTreemap layers={layers} tileBorderRadius={8}/>
const treemap = new Treemap<Datum>({ layers, tileBorderRadius: 8 })
Labels​
Internal Node Labels​
By default, only leaf nodes (tiles with no children) are labeled. Set labelInternalNodes
to true
to show labels for parent nodes as well:
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisTreemap layers={layers} labelInternalNodes={true}/>
<vis-treemap
[layers]="layers"
[labelInternalNodes]="true"
></vis-treemap>
<VisTreemap {layers} labelInternalNodes={true}/>
<VisTreemap :layers="layers" :labelInternalNodes="true" />
<VisTreemap layers={layers} labelInternalNodes={true}/>
const treemap = new Treemap<Datum>({ layers, labelInternalNodes: true })
Label Positioning​
Adjust the position of labels using the labelOffsetX
and labelOffsetY
properties:
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisTreemap layers={layers} labelOffsetX={8} labelOffsetY={8}/>
<vis-treemap
[layers]="layers"
[labelOffsetX]="8"
[labelOffsetY]="8"
></vis-treemap>
<VisTreemap {layers} labelOffsetX={8} labelOffsetY={8}/>
<VisTreemap :layers="layers" :labelOffsetX="8" :labelOffsetY="8" />
<VisTreemap layers={layers} labelOffsetX={8} labelOffsetY={8}/>
const treemap = new Treemap<Datum>({ layers, labelOffsetX: 8, labelOffsetY: 8 })
Dynamic Label Size​
Enable font size variation based on tile size with enableTileLabelFontSizeVariation
:
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisTreemap layers={layers} enableTileLabelFontSizeVariation={true}/>
<vis-treemap
[layers]="layers"
[enableTileLabelFontSizeVariation]="true"
></vis-treemap>
<VisTreemap {layers} enableTileLabelFontSizeVariation={true}/>
<VisTreemap
:layers="layers"
:enableTileLabelFontSizeVariation="true"
/>
<VisTreemap layers={layers} enableTileLabelFontSizeVariation={true}/>
const treemap = new Treemap<Datum>({ layers, enableTileLabelFontSizeVariation: true })
You can customize the font sizes used with:
tileLabelSmallFontSize
: Font size for small tiles (default: 8px)tileLabelMediumFontSize
: Font size for medium tiles (default: 12px)tileLabelLargeFontSize
: Font size for large tiles (default: 22px)
Advanced Features​
Lightness Variance​
Enable subtle lightness variation between sibling tiles to improve visual distinction:
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisTreemap layers={layers} enableLightnessVariance={true}/>
<vis-treemap
[layers]="layers"
[enableLightnessVariance]="true"
></vis-treemap>
<VisTreemap {layers} enableLightnessVariance={true}/>
<VisTreemap :layers="layers" :enableLightnessVariance="true" />
<VisTreemap layers={layers} enableLightnessVariance={true}/>
const treemap = new Treemap<Datum>({ layers, enableLightnessVariance: true })
Click Affordance​
Indicate that tiles are clickable by setting showTileClickAffordance
to true
:
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisTreemap layers={layers} showTileClickAffordance={true}/>
<vis-treemap
[layers]="layers"
[showTileClickAffordance]="true"
></vis-treemap>
<VisTreemap {layers} showTileClickAffordance={true}/>
<VisTreemap :layers="layers" :showTileClickAffordance="true" />
<VisTreemap layers={layers} showTileClickAffordance={true}/>
const treemap = new Treemap<Datum>({ layers, showTileClickAffordance: true })
Layout Options​
Top Padding for Internal Nodes​
Add extra space at the top of parent tiles to accommodate labels with tilePaddingTop
:
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisTreemap
layers={layers}
labelInternalNodes={true}
tilePaddingTop={20}
/>
<vis-treemap
[layers]="layers"
[labelInternalNodes]="true"
[tilePaddingTop]="20"
></vis-treemap>
<VisTreemap {layers} labelInternalNodes={true} tilePaddingTop={20}/>
<VisTreemap
:layers="layers"
:labelInternalNodes="true"
:tilePaddingTop="20"
/>
<VisTreemap
layers={layers}
labelInternalNodes={true}
tilePaddingTop={20}
/>
const treemap = new Treemap<Datum>({
layers,
labelInternalNodes: true,
tilePaddingTop: 20
})
CSS Variables​
Treemap supports the following CSS variables:
--vis-treemap-tile-stroke-color: #fff;
--vis-treemap-tile-stroke-width: 2px;
--vis-treemap-tile-hover-stroke-color: #fff;
--vis-treemap-tile-fill-color: #B9BEC3;
--vis-treemap-tile-background-color: #fff;
--vis-treemap-tile-cursor: default;
--vis-treemap-label-text-color: #000;
--vis-treemap-label-font-size: 12px;
--vis-treemap-label-opacity: 0.8;
/* Dark Theme */
--vis-dark-treemap-tile-stroke-color: #2c2c2c;
--vis-dark-treemap-tile-fill-color: #5b5f6d;
--vis-dark-treemap-label-text-color: #5b5f6d;
Note: The label color is now controlled by the CSS variable
--vis-treemap-label-text-color
(and--vis-dark-treemap-label-text-color
for dark theme). This makes it easy to theme the treemap labels for light and dark modes.
Component Props​
Name | Type | Description |
---|---|---|
* required property |