Skip to content

Commit

Permalink
feat(heatmap): restore size variation support
Browse files Browse the repository at this point in the history
  • Loading branch information
plouc committed Jan 12, 2022
1 parent a91066f commit 849c7d7
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 73 deletions.
3 changes: 2 additions & 1 deletion packages/heatmap/src/HeatMap.tsx
Expand Up @@ -32,7 +32,7 @@ const InnerHeatMap = <Datum extends HeatMapDatum, ExtraProps extends object>({
xOuterPadding = svgDefaultProps.xOuterPadding,
yInnerPadding = svgDefaultProps.yInnerPadding,
yOuterPadding = svgDefaultProps.yOuterPadding,
// sizeVariation = svgDefaultProps.sizeVariation,
sizeVariation = svgDefaultProps.sizeVariation,
cellComponent = svgDefaultProps.cellComponent as NonNullable<
HeatMapSvgProps<Datum, ExtraProps>['cellComponent']
>,
Expand Down Expand Up @@ -85,6 +85,7 @@ const InnerHeatMap = <Datum extends HeatMapDatum, ExtraProps extends object>({
xOuterPadding,
yInnerPadding,
yOuterPadding,
sizeVariation,
colors,
emptyColor,
opacity,
Expand Down
3 changes: 2 additions & 1 deletion packages/heatmap/src/HeatMapCanvas.tsx
Expand Up @@ -34,7 +34,7 @@ const InnerHeatMapCanvas = <Datum extends HeatMapDatum, ExtraProps extends objec
xOuterPadding = canvasDefaultProps.xOuterPadding,
yInnerPadding = canvasDefaultProps.yInnerPadding,
yOuterPadding = canvasDefaultProps.yOuterPadding,
// sizeVariation = canvasDefaultProps.sizeVariation,
sizeVariation = canvasDefaultProps.sizeVariation,
renderCell: _renderCell = canvasDefaultProps.renderCell as CellShape,
opacity = canvasDefaultProps.opacity,
activeOpacity = canvasDefaultProps.activeOpacity,
Expand Down Expand Up @@ -84,6 +84,7 @@ const InnerHeatMapCanvas = <Datum extends HeatMapDatum, ExtraProps extends objec
xOuterPadding,
yInnerPadding,
yOuterPadding,
sizeVariation,
colors,
emptyColor,
opacity,
Expand Down
84 changes: 24 additions & 60 deletions packages/heatmap/src/hooks.ts
@@ -1,4 +1,5 @@
import { useMemo, useCallback, useState } from 'react'
import { scaleLinear } from 'd3-scale'
import { useTheme, usePropertyAccessor, useValueFormatter } from '@nivo/core'
import { useInheritedColor, getContinuousColorScale } from '@nivo/colors'
import { AnnotationMatcher, useAnnotations } from '@nivo/annotations'
Expand All @@ -8,6 +9,7 @@ import {
HeatMapCommonProps,
HeatMapDataProps,
HeatMapDatum,
SizeVariationConfig,
} from './types'
import { commonDefaultProps } from './defaults'
import { computeCells } from './compute'
Expand Down Expand Up @@ -43,15 +45,6 @@ export const useComputeCells = <Datum extends HeatMapDatum, ExtraProps extends o
[data, width, height, xInnerPadding, xOuterPadding, yInnerPadding, yOuterPadding]
)

/*
const computeX = (column: number, cellWidth: number, padding: number) => {
return column * cellWidth + cellWidth * 0.5 + padding * column + padding
}
const computeY = (row: number, cellHeight: number, padding: number) => {
return row * cellHeight + cellHeight * 0.5 + padding * row + padding
}
*/

const isHoverTargetByType = {
cell: <Datum extends HeatMapDatum>(
cell: Omit<
Expand Down Expand Up @@ -83,58 +76,23 @@ const isHoverTargetByType = {
) => cell.serieId === current.serieId || cell.data.x === current.data.x,
}

/*
const computeCells = <Datum extends object>({
data,
keys,
getIndex,
xScale,
yScale,
sizeScale,
cellOpacity,
cellWidth,
cellHeight,
colorScale,
nanColor,
getLabel,
getLabelTextColor,
}: {
data: HeatMapDataProps<Datum>['data']
keys: HeatMapCommonProps<Datum>['keys']
getIndex: (datum: Datum) => string | number
}) => {
const cells = []
data.forEach(datum => {
keys.forEach(key => {
const value = datum[key]
const label = getLabel(datum, key)
const index = getIndex(datum)
const sizeMultiplier = sizeScale ? sizeScale(value) : 1
const width = sizeMultiplier * cellWidth
const height = sizeMultiplier * cellHeight
const useSizeScale = (
size: false | SizeVariationConfig,
min: number,
max: number
): ((value: number | null) => number) =>
useMemo(() => {
if (!size) return () => 1

const cell = {
id: `${key}.${index}`,
xKey: key,
yKey: index,
x: xScale(key),
y: yScale(index),
width,
height,
value,
label,
color: isNaN(value) ? nanColor : colorScale(value),
opacity: cellOpacity,
}
cell.labelTextColor = getLabelTextColor(cell)
cells.push(cell)
})
})
const scale = scaleLinear()
.domain(size.values ? size.values : [min, max])
.range(size.sizes)

return cells
}
*/
return (value: number | null) => {
if (value === null) return 1
return scale(value)
}
}, [size, min, max])

export const useHeatMap = <
Datum extends HeatMapDatum = DefaultHeatMapDatum,
Expand All @@ -149,7 +107,7 @@ export const useHeatMap = <
xInnerPadding = commonDefaultProps.xInnerPadding,
yOuterPadding = commonDefaultProps.yOuterPadding,
yInnerPadding = commonDefaultProps.yInnerPadding,
// sizeVariation,
sizeVariation = commonDefaultProps.sizeVariation,
colors = commonDefaultProps.colors as HeatMapCommonProps<Datum>['colors'],
emptyColor = commonDefaultProps.emptyColor,
opacity = commonDefaultProps.opacity,
Expand Down Expand Up @@ -220,6 +178,7 @@ export const useHeatMap = <
},
[colors, colorScale, emptyColor]
)
const getSize = useSizeScale(sizeVariation, minValue, maxValue)
const theme = useTheme()
const getBorderColor = useInheritedColor(borderColor, theme)
const getLabelTextColor = useInheritedColor(labelTextColor, theme)
Expand All @@ -234,8 +193,12 @@ export const useHeatMap = <
computedOpacity = activeIds.includes(cell.id) ? activeOpacity : inactiveOpacity
}

const sizeMultiplier = getSize(cell.value)

const computedCell = {
...cell,
width: cell.width * sizeMultiplier,
height: cell.height * sizeMultiplier,
formattedValue: cell.value !== null ? formatValue(cell.value) : null,
opacity: computedOpacity,
} as ComputedCell<Datum>
Expand All @@ -249,6 +212,7 @@ export const useHeatMap = <
}),
[
cells,
getSize,
getColor,
getBorderColor,
getLabelTextColor,
Expand Down
4 changes: 3 additions & 1 deletion packages/heatmap/src/types.ts
Expand Up @@ -63,7 +63,9 @@ export interface HeatMapDataProps<Datum extends HeatMapDatum, ExtraProps extends
}

export interface SizeVariationConfig {
values: [min: number, max: number]
// use auto min/max values if unspecified
values?: [min: number, max: number]
// expressed as a range from 0~1
sizes: [min: number, max: number]
}

Expand Down
23 changes: 14 additions & 9 deletions website/src/data/components/heatmap/props.ts
Expand Up @@ -107,17 +107,22 @@ const props: ChartProperty[] = [
},
{
key: 'sizeVariation',
help: 'Cell size variation.',
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.`,
help: 'Optionally make the size of the cells vary depending on their value.',
description: `
To enable this feature, you can use the following config:
\`\`\`
interface SizeVariationConfig {
// use auto min/max values if unspecified
values?: [min: number, max: number]
// expressed as a range from 0~1
sizes: [min: number, max: number]
}
\`\`\`
`,
defaultValue: defaults.sizeVariation,
type: 'number',
type: 'false | SizeVariationConfig',
group: 'Base',
control: {
type: 'range',
min: 0,
max: 1,
step: 0.02,
},
},
themeProperty(allFlavors),
{
Expand Down
2 changes: 1 addition & 1 deletion website/src/lib/componentProperties.ts
Expand Up @@ -10,7 +10,7 @@ export const themeProperty = (flavors: Flavor[]): ChartProperty => ({
help: 'Define style for common elements such as labels, axes…',
flavors,
description: `
Please have a look at [the dedicated guide](self:/guides/theming)
Please have a look at [the dedicated guide](self:/guides/theming/)
on how to define a theme for your charts.
`,
})
Expand Down

0 comments on commit 849c7d7

Please sign in to comment.