Skip to content

Commit 849c7d7

Browse files
committedJan 12, 2022
feat(heatmap): restore size variation support
1 parent a91066f commit 849c7d7

File tree

6 files changed

+46
-73
lines changed

6 files changed

+46
-73
lines changed
 

‎packages/heatmap/src/HeatMap.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ const InnerHeatMap = <Datum extends HeatMapDatum, ExtraProps extends object>({
3232
xOuterPadding = svgDefaultProps.xOuterPadding,
3333
yInnerPadding = svgDefaultProps.yInnerPadding,
3434
yOuterPadding = svgDefaultProps.yOuterPadding,
35-
// sizeVariation = svgDefaultProps.sizeVariation,
35+
sizeVariation = svgDefaultProps.sizeVariation,
3636
cellComponent = svgDefaultProps.cellComponent as NonNullable<
3737
HeatMapSvgProps<Datum, ExtraProps>['cellComponent']
3838
>,
@@ -85,6 +85,7 @@ const InnerHeatMap = <Datum extends HeatMapDatum, ExtraProps extends object>({
8585
xOuterPadding,
8686
yInnerPadding,
8787
yOuterPadding,
88+
sizeVariation,
8889
colors,
8990
emptyColor,
9091
opacity,

‎packages/heatmap/src/HeatMapCanvas.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ const InnerHeatMapCanvas = <Datum extends HeatMapDatum, ExtraProps extends objec
3434
xOuterPadding = canvasDefaultProps.xOuterPadding,
3535
yInnerPadding = canvasDefaultProps.yInnerPadding,
3636
yOuterPadding = canvasDefaultProps.yOuterPadding,
37-
// sizeVariation = canvasDefaultProps.sizeVariation,
37+
sizeVariation = canvasDefaultProps.sizeVariation,
3838
renderCell: _renderCell = canvasDefaultProps.renderCell as CellShape,
3939
opacity = canvasDefaultProps.opacity,
4040
activeOpacity = canvasDefaultProps.activeOpacity,
@@ -84,6 +84,7 @@ const InnerHeatMapCanvas = <Datum extends HeatMapDatum, ExtraProps extends objec
8484
xOuterPadding,
8585
yInnerPadding,
8686
yOuterPadding,
87+
sizeVariation,
8788
colors,
8889
emptyColor,
8990
opacity,

‎packages/heatmap/src/hooks.ts

+24-60
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { useMemo, useCallback, useState } from 'react'
2+
import { scaleLinear } from 'd3-scale'
23
import { useTheme, usePropertyAccessor, useValueFormatter } from '@nivo/core'
34
import { useInheritedColor, getContinuousColorScale } from '@nivo/colors'
45
import { AnnotationMatcher, useAnnotations } from '@nivo/annotations'
@@ -8,6 +9,7 @@ import {
89
HeatMapCommonProps,
910
HeatMapDataProps,
1011
HeatMapDatum,
12+
SizeVariationConfig,
1113
} from './types'
1214
import { commonDefaultProps } from './defaults'
1315
import { computeCells } from './compute'
@@ -43,15 +45,6 @@ export const useComputeCells = <Datum extends HeatMapDatum, ExtraProps extends o
4345
[data, width, height, xInnerPadding, xOuterPadding, yInnerPadding, yOuterPadding]
4446
)
4547

46-
/*
47-
const computeX = (column: number, cellWidth: number, padding: number) => {
48-
return column * cellWidth + cellWidth * 0.5 + padding * column + padding
49-
}
50-
const computeY = (row: number, cellHeight: number, padding: number) => {
51-
return row * cellHeight + cellHeight * 0.5 + padding * row + padding
52-
}
53-
*/
54-
5548
const isHoverTargetByType = {
5649
cell: <Datum extends HeatMapDatum>(
5750
cell: Omit<
@@ -83,58 +76,23 @@ const isHoverTargetByType = {
8376
) => cell.serieId === current.serieId || cell.data.x === current.data.x,
8477
}
8578

86-
/*
87-
const computeCells = <Datum extends object>({
88-
data,
89-
keys,
90-
getIndex,
91-
xScale,
92-
yScale,
93-
sizeScale,
94-
cellOpacity,
95-
cellWidth,
96-
cellHeight,
97-
colorScale,
98-
nanColor,
99-
getLabel,
100-
getLabelTextColor,
101-
}: {
102-
data: HeatMapDataProps<Datum>['data']
103-
keys: HeatMapCommonProps<Datum>['keys']
104-
getIndex: (datum: Datum) => string | number
105-
}) => {
106-
const cells = []
107-
data.forEach(datum => {
108-
keys.forEach(key => {
109-
const value = datum[key]
110-
const label = getLabel(datum, key)
111-
const index = getIndex(datum)
112-
const sizeMultiplier = sizeScale ? sizeScale(value) : 1
113-
const width = sizeMultiplier * cellWidth
114-
const height = sizeMultiplier * cellHeight
79+
const useSizeScale = (
80+
size: false | SizeVariationConfig,
81+
min: number,
82+
max: number
83+
): ((value: number | null) => number) =>
84+
useMemo(() => {
85+
if (!size) return () => 1
11586

116-
const cell = {
117-
id: `${key}.${index}`,
118-
xKey: key,
119-
yKey: index,
120-
x: xScale(key),
121-
y: yScale(index),
122-
width,
123-
height,
124-
value,
125-
label,
126-
color: isNaN(value) ? nanColor : colorScale(value),
127-
opacity: cellOpacity,
128-
}
129-
cell.labelTextColor = getLabelTextColor(cell)
130-
131-
cells.push(cell)
132-
})
133-
})
87+
const scale = scaleLinear()
88+
.domain(size.values ? size.values : [min, max])
89+
.range(size.sizes)
13490

135-
return cells
136-
}
137-
*/
91+
return (value: number | null) => {
92+
if (value === null) return 1
93+
return scale(value)
94+
}
95+
}, [size, min, max])
13896

13997
export const useHeatMap = <
14098
Datum extends HeatMapDatum = DefaultHeatMapDatum,
@@ -149,7 +107,7 @@ export const useHeatMap = <
149107
xInnerPadding = commonDefaultProps.xInnerPadding,
150108
yOuterPadding = commonDefaultProps.yOuterPadding,
151109
yInnerPadding = commonDefaultProps.yInnerPadding,
152-
// sizeVariation,
110+
sizeVariation = commonDefaultProps.sizeVariation,
153111
colors = commonDefaultProps.colors as HeatMapCommonProps<Datum>['colors'],
154112
emptyColor = commonDefaultProps.emptyColor,
155113
opacity = commonDefaultProps.opacity,
@@ -220,6 +178,7 @@ export const useHeatMap = <
220178
},
221179
[colors, colorScale, emptyColor]
222180
)
181+
const getSize = useSizeScale(sizeVariation, minValue, maxValue)
223182
const theme = useTheme()
224183
const getBorderColor = useInheritedColor(borderColor, theme)
225184
const getLabelTextColor = useInheritedColor(labelTextColor, theme)
@@ -234,8 +193,12 @@ export const useHeatMap = <
234193
computedOpacity = activeIds.includes(cell.id) ? activeOpacity : inactiveOpacity
235194
}
236195

196+
const sizeMultiplier = getSize(cell.value)
197+
237198
const computedCell = {
238199
...cell,
200+
width: cell.width * sizeMultiplier,
201+
height: cell.height * sizeMultiplier,
239202
formattedValue: cell.value !== null ? formatValue(cell.value) : null,
240203
opacity: computedOpacity,
241204
} as ComputedCell<Datum>
@@ -249,6 +212,7 @@ export const useHeatMap = <
249212
}),
250213
[
251214
cells,
215+
getSize,
252216
getColor,
253217
getBorderColor,
254218
getLabelTextColor,

‎packages/heatmap/src/types.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,9 @@ export interface HeatMapDataProps<Datum extends HeatMapDatum, ExtraProps extends
6363
}
6464

6565
export interface SizeVariationConfig {
66-
values: [min: number, max: number]
66+
// use auto min/max values if unspecified
67+
values?: [min: number, max: number]
68+
// expressed as a range from 0~1
6769
sizes: [min: number, max: number]
6870
}
6971

‎website/src/data/components/heatmap/props.ts

+14-9
Original file line numberDiff line numberDiff line change
@@ -107,17 +107,22 @@ const props: ChartProperty[] = [
107107
},
108108
{
109109
key: 'sizeVariation',
110-
help: 'Cell size variation.',
111-
description: `Size variation (0~1), if value is 0 size won't be affected. If you use for example the value 0.3, cell width/height will vary between 0.7~1 according to its corresponding value.`,
110+
help: 'Optionally make the size of the cells vary depending on their value.',
111+
description: `
112+
To enable this feature, you can use the following config:
113+
114+
\`\`\`
115+
interface SizeVariationConfig {
116+
// use auto min/max values if unspecified
117+
values?: [min: number, max: number]
118+
// expressed as a range from 0~1
119+
sizes: [min: number, max: number]
120+
}
121+
\`\`\`
122+
`,
112123
defaultValue: defaults.sizeVariation,
113-
type: 'number',
124+
type: 'false | SizeVariationConfig',
114125
group: 'Base',
115-
control: {
116-
type: 'range',
117-
min: 0,
118-
max: 1,
119-
step: 0.02,
120-
},
121126
},
122127
themeProperty(allFlavors),
123128
{

‎website/src/lib/componentProperties.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export const themeProperty = (flavors: Flavor[]): ChartProperty => ({
1010
help: 'Define style for common elements such as labels, axes…',
1111
flavors,
1212
description: `
13-
Please have a look at [the dedicated guide](self:/guides/theming)
13+
Please have a look at [the dedicated guide](self:/guides/theming/)
1414
on how to define a theme for your charts.
1515
`,
1616
})

0 commit comments

Comments
 (0)
Please sign in to comment.