Skip to content

Commit

Permalink
feat(pie): add radius offsets support for active arcs
Browse files Browse the repository at this point in the history
  • Loading branch information
plouc committed Dec 18, 2020
1 parent 3eece0a commit cfc0cb6
Show file tree
Hide file tree
Showing 9 changed files with 97 additions and 12 deletions.
3 changes: 3 additions & 0 deletions packages/arcs/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# `@nivo/arcs`

[![version](https://img.shields.io/npm/v/@nivo/arcs.svg?style=flat-square)](https://www.npmjs.com/package/@nivo/arcs)

This package is used internally by nivo packages dealing with arcs
such as `@nivo/pie`, `@nivo/chord` and `@nivo/sunburst`.
4 changes: 4 additions & 0 deletions packages/pie/src/Pie.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ const Pie = <RawDatum,>({
fit = defaultProps.fit,
innerRadius: innerRadiusRatio = defaultProps.innerRadius,
cornerRadius = defaultProps.cornerRadius,
activeInnerRadiusOffset = defaultProps.activeInnerRadiusOffset,
activeOuterRadiusOffset = defaultProps.activeOuterRadiusOffset,

width,
height,
Expand Down Expand Up @@ -111,6 +113,8 @@ const Pie = <RawDatum,>({
padAngle,
sortByValue,
cornerRadius,
activeInnerRadiusOffset,
activeOuterRadiusOffset,
})

const boundDefs = bindDefs(defs, dataWithArc, fill)
Expand Down
8 changes: 7 additions & 1 deletion packages/pie/src/PieCanvas.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ const PieCanvas = <RawDatum, >({
fit = defaultProps.fit,
innerRadius: innerRadiusRatio = defaultProps.innerRadius,
cornerRadius = defaultProps.cornerRadius,
activeInnerRadiusOffset = defaultProps.activeInnerRadiusOffset,
activeOuterRadiusOffset = defaultProps.activeOuterRadiusOffset,

width,
height,
Expand Down Expand Up @@ -136,7 +138,7 @@ const PieCanvas = <RawDatum, >({
colors,
})

const { dataWithArc, arcGenerator, centerX, centerY, radius, innerRadius } = usePieFromBox<RawDatum>({
const { dataWithArc, arcGenerator, centerX, centerY, radius, innerRadius, setActiveId } = usePieFromBox<RawDatum>({
data: normalizedData,
width: innerWidth,
height: innerHeight,
Expand All @@ -147,6 +149,8 @@ const PieCanvas = <RawDatum, >({
padAngle,
sortByValue,
cornerRadius,
activeInnerRadiusOffset,
activeOuterRadiusOffset,
})

const getBorderColor = useInheritedColor<ComputedDatum<RawDatum>>(borderColor, theme)
Expand Down Expand Up @@ -288,8 +292,10 @@ const PieCanvas = <RawDatum, >({
const datum = getArcFromMouse(event)
if (datum) {
onMouseMove?.(datum, event)
setActiveId(datum.id)
showTooltipFromEvent(createElement(tooltip, { datum }), event)
} else {
setActiveId(null)
hideTooltip()
}
}
Expand Down
58 changes: 47 additions & 11 deletions packages/pie/src/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,15 @@ export const useNormalizedData = <RawDatum extends MayHaveLabel>({
*/
export const usePieArcs = <RawDatum>({
data,
startAngle = defaultProps.startAngle,
endAngle = defaultProps.endAngle,
startAngle,
endAngle,
innerRadius,
outerRadius,
padAngle = defaultProps.padAngle,
sortByValue = defaultProps.sortByValue,
activeId = null,
padAngle,
sortByValue,
activeId,
activeInnerRadiusOffset,
activeOuterRadiusOffset,
}: {
data: Omit<ComputedDatum<RawDatum>, 'arc' | 'fill'>[]
// in degrees
Expand All @@ -117,7 +119,9 @@ export const usePieArcs = <RawDatum>({
outerRadius: number
padAngle: number
sortByValue: boolean
activeId?: null | string | number
activeId: null | string | number
activeInnerRadiusOffset: number
activeOuterRadiusOffset: number
}): Omit<ComputedDatum<RawDatum>, 'fill'>[] => {
const pie = useMemo(() => {
const innerPie = d3Pie<Omit<ComputedDatum<RawDatum>, 'arc' | 'fill'>>()
Expand Down Expand Up @@ -152,8 +156,14 @@ export const usePieArcs = <RawDatum>({
index: arc.index,
startAngle: arc.startAngle,
endAngle: arc.endAngle,
innerRadius: innerRadius,
outerRadius: activeId === arc.data.id ? outerRadius + 20 : outerRadius,
innerRadius:
activeId === arc.data.id
? innerRadius - activeInnerRadiusOffset
: innerRadius,
outerRadius:
activeId === arc.data.id
? outerRadius + activeOuterRadiusOffset
: outerRadius,
thickness: outerRadius - innerRadius,
padAngle: arc.padAngle,
angle,
Expand All @@ -163,7 +173,15 @@ export const usePieArcs = <RawDatum>({
}
),

[pie, data, innerRadius, outerRadius, activeId]
[
pie,
data,
innerRadius,
outerRadius,
activeId,
activeInnerRadiusOffset,
activeInnerRadiusOffset,
]
)
}

Expand All @@ -180,14 +198,23 @@ export const usePie = <RawDatum>({
padAngle = defaultProps.padAngle,
sortByValue = defaultProps.sortByValue,
cornerRadius = defaultProps.cornerRadius,
activeInnerRadiusOffset = defaultProps.activeInnerRadiusOffset,
activeOuterRadiusOffset = defaultProps.activeOuterRadiusOffset,
}: Pick<
CompletePieSvgProps<RawDatum>,
'startAngle' | 'endAngle' | 'padAngle' | 'sortByValue' | 'cornerRadius'
| 'startAngle'
| 'endAngle'
| 'padAngle'
| 'sortByValue'
| 'cornerRadius'
| 'activeInnerRadiusOffset'
| 'activeOuterRadiusOffset'
> & {
data: Omit<ComputedDatum<RawDatum>, 'arc'>[]
radius: number
innerRadius: number
}) => {
const [activeId, setActiveId] = useState<string | number | null>(null)
const dataWithArc = usePieArcs({
data,
startAngle,
Expand All @@ -196,11 +223,14 @@ export const usePie = <RawDatum>({
outerRadius: radius,
padAngle,
sortByValue,
activeId,
activeInnerRadiusOffset,
activeOuterRadiusOffset,
})

const arcGenerator = useArcGenerator({ cornerRadius })

return { dataWithArc, arcGenerator }
return { dataWithArc, arcGenerator, setActiveId }
}

/**
Expand All @@ -222,6 +252,8 @@ export const usePieFromBox = <RawDatum>({
sortByValue = defaultProps.sortByValue,
cornerRadius = defaultProps.cornerRadius,
fit = defaultProps.fit,
activeInnerRadiusOffset = defaultProps.activeInnerRadiusOffset,
activeOuterRadiusOffset = defaultProps.activeOuterRadiusOffset,
}: Pick<
CompletePieSvgProps<RawDatum>,
| 'width'
Expand All @@ -233,6 +265,8 @@ export const usePieFromBox = <RawDatum>({
| 'sortByValue'
| 'cornerRadius'
| 'fit'
| 'activeInnerRadiusOffset'
| 'activeOuterRadiusOffset'
> & {
data: Omit<ComputedDatum<RawDatum>, 'arc'>[]
}) => {
Expand Down Expand Up @@ -294,6 +328,8 @@ export const usePieFromBox = <RawDatum>({
padAngle,
sortByValue,
activeId,
activeInnerRadiusOffset,
activeOuterRadiusOffset,
})

const arcGenerator = useArcGenerator({
Expand Down
2 changes: 2 additions & 0 deletions packages/pie/src/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ export const defaultProps = {
startAngle: 0,
endAngle: 360,
fit: true,
activeInnerRadiusOffset: 0,
activeOuterRadiusOffset: 0,

// border
borderWidth: 0,
Expand Down
2 changes: 2 additions & 0 deletions packages/pie/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ export type CommonPieProps<RawDatum> = {
startAngle: number
endAngle: number
fit: boolean
activeInnerRadiusOffset: number
activeOuterRadiusOffset: number

// colors, theme and border
colors: OrdinalColorScaleConfig<Omit<ComputedDatum<RawDatum>, 'color' | 'fill' | 'arc'>>
Expand Down
28 changes: 28 additions & 0 deletions website/src/data/components/pie/props.js
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,34 @@ const props = [
defaultValue: defaultProps.isInteractive,
controlType: 'switch',
},
{
key: 'activeInnerRadiusOffset',
help: `Skip label if corresponding slice's angle is lower than provided value.`,
type: 'number',
required: false,
defaultValue: defaultProps.activeInnerRadiusOffset,
controlType: 'range',
group: 'Interactivity',
controlOptions: {
unit: 'px',
min: 0,
max: 50,
},
},
{
key: 'activeOuterRadiusOffset',
help: `Skip label if corresponding slice's angle is lower than provided value.`,
type: 'number',
required: false,
defaultValue: defaultProps.activeOuterRadiusOffset,
controlType: 'range',
group: 'Interactivity',
controlOptions: {
unit: 'px',
min: 0,
max: 50,
},
},
{
key: 'onMouseEnter',
flavors: ['svg'],
Expand Down
2 changes: 2 additions & 0 deletions website/src/pages/pie/canvas.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ const initialProperties = {
padAngle: 0.7,
cornerRadius: 3,
fit: true,
activeInnerRadiusOffset: defaultProps.activeInnerRadiusOffset,
activeOuterRadiusOffset: 16,

colors: { scheme: 'paired' },

Expand Down
2 changes: 2 additions & 0 deletions website/src/pages/pie/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ const initialProperties = {
padAngle: 0.7,
cornerRadius: 3,
fit: defaultProps.fit,
activeInnerRadiusOffset: defaultProps.activeInnerRadiusOffset,
activeOuterRadiusOffset: 16,

colors: defaultProps.colors,

Expand Down

0 comments on commit cfc0cb6

Please sign in to comment.