Skip to content

Commit d09fb93

Browse files
committed
fix: mixed axis stacking voronoi
1 parent ac8f167 commit d09fb93

File tree

6 files changed

+103
-55
lines changed

6 files changed

+103
-55
lines changed

src/components/Chart.tsx

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import {
2525
materializeStyles,
2626
getSeriesStatus,
2727
getDatumStatus,
28-
sortDatums,
28+
sortDatumsBySecondaryPx,
2929
} from '../utils/Utils'
3030
import buildAxisLinear from '../utils/buildAxis.linear'
3131
import { ChartContextProvider } from '../utils/chartContext'
@@ -70,7 +70,7 @@ function defaultChartOptions<TDatum>(
7070
getSeriesOrder:
7171
options.getSeriesOrder ?? ((series: Series<TDatum>[]) => series),
7272
interactionMode: options.interactionMode ?? 'primary',
73-
showVoronoi: options.showVoronoi ?? false,
73+
showVoronoi: options.showVoronoi ?? true,
7474
defaultColors: options.defaultColors ?? defaultColorScheme,
7575
useIntersectionObserver: options.useIntersectionObserver ?? true,
7676
intersectionObserverRootMargin:
@@ -269,7 +269,10 @@ function ChartInner<TDatum>({
269269
optionsWithScaleType.stacked = true
270270
}
271271

272-
return { position: !i ? 'left' : 'right', ...optionsWithScaleType }
272+
return {
273+
position: !i ? 'left' : 'right',
274+
...optionsWithScaleType,
275+
}
273276
}
274277
)
275278
}, [options.data, options.secondaryAxes, primaryAxisOptions])
@@ -491,11 +494,17 @@ function ChartInner<TDatum>({
491494
})
492495

493496
datumsByInteractionGroup.forEach((value, key) => {
494-
datumsByInteractionGroup.set(key, sortDatums(value, secondaryAxes))
497+
datumsByInteractionGroup.set(
498+
key,
499+
sortDatumsBySecondaryPx(value, secondaryAxes)
500+
)
495501
})
496502

497503
datumsByTooltipGroup.forEach((value, key) => {
498-
datumsByTooltipGroup.set(key, sortDatums(value, secondaryAxes))
504+
datumsByTooltipGroup.set(
505+
key,
506+
sortDatumsBySecondaryPx(value, secondaryAxes)
507+
)
499508
})
500509

501510
allDatums.forEach(datum => {
@@ -506,7 +515,12 @@ function ChartInner<TDatum>({
506515
})
507516

508517
return [datumsByInteractionGroup, datumsByTooltipGroup]
509-
}, [allDatums, options.interactionMode, tooltipOptions.groupingMode])
518+
}, [
519+
allDatums,
520+
options.interactionMode,
521+
secondaryAxes,
522+
tooltipOptions.groupingMode,
523+
])
510524

511525
const getSeriesStatusStyle = React.useCallback(
512526
(series: Series<TDatum>, focusedDatum: Datum<TDatum> | null) => {

src/components/Tooltip.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ export default function Tooltip<TDatum>(): React.ReactPortal | null {
187187
getOptions,
188188
focusedDatum: latestFocusedDatum,
189189
primaryAxis,
190+
secondaryAxes,
190191
secondaryAxis,
191192
getDatumStyle: (datum: Datum<TDatum>) =>
192193
getDatumStatusStyle(datum, focusedDatum),

src/components/TooltipRenderer.tsx

Lines changed: 50 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export type TooltipRendererProps<TDatum> = {
2525
focusedDatum: Datum<TDatum> | null
2626
getOptions: () => ResolvedChartOptions<TDatum>
2727
primaryAxis: Axis<TDatum>
28+
secondaryAxes: Axis<TDatum>[]
2829
secondaryAxis: Axis<TDatum>
2930
getDatumStyle: (datum: Datum<TDatum>) => CSSProperties
3031
anchor: ReturnType<typeof useAnchor>
@@ -325,47 +326,58 @@ function TooltipRenderer<TDatum>(props: TooltipRendererProps<TDatum>) {
325326
<td />
326327
</tr>
327328
) : null}
328-
{secondaryAxis.stacked &&
329-
(focusedDatum.tooltipGroup ?? []).length > 1 ? (
330-
<tr>
331-
<td
332-
style={{
333-
paddingTop: '5px',
334-
}}
335-
>
336-
<div
337-
style={{
338-
width: '12px',
339-
height: '12px',
340-
backgroundColor: dark
341-
? 'rgba(0, 26, 39, 0.3)'
342-
: 'rgba(255,255,255,.2)',
343-
borderRadius: '50px',
344-
}}
345-
/>
346-
</td>
347-
<td
348-
style={{
349-
paddingTop: '5px',
350-
}}
351-
>
352-
Total: &nbsp;
353-
</td>
354-
<td
355-
style={{
356-
paddingTop: '5px',
357-
}}
358-
>
359-
{/* {secondaryAxis.format(
329+
{(focusedDatum.tooltipGroup ?? []).length > 1
330+
? props.secondaryAxes
331+
.filter(d => d.stacked)
332+
.map((secondaryAxis, i) => {
333+
return (
334+
<tr key={`${secondaryAxis.id}_${i}`}>
335+
<td
336+
style={{
337+
paddingTop: '5px',
338+
}}
339+
>
340+
<div
341+
style={{
342+
width: '12px',
343+
height: '12px',
344+
backgroundColor: dark
345+
? 'rgba(0, 26, 39, 0.3)'
346+
: 'rgba(255,255,255,.2)',
347+
borderRadius: '50px',
348+
}}
349+
/>
350+
</td>
351+
<td
352+
style={{
353+
paddingTop: '5px',
354+
}}
355+
>
356+
{props.secondaryAxes.length > 1
357+
? secondaryAxis.id ?? `Axis ${i + 1} `
358+
: ''}
359+
Total: &nbsp;
360+
</td>
361+
<td
362+
style={{
363+
paddingTop: '5px',
364+
}}
365+
>
366+
{/* {secondaryAxis.format(
360367
[...focusedDatum.group].reverse()[0].totalValue,
361368
-1
362369
)} */}
363-
{(secondaryAxis as AxisLinear<any>).formatters.scale(
364-
sum(focusedDatum.tooltipGroup ?? [], d => d.secondaryValue)
365-
)}
366-
</td>
367-
</tr>
368-
) : null}
370+
{(secondaryAxis as AxisLinear<any>).formatters.scale(
371+
sum(
372+
focusedDatum.tooltipGroup ?? [],
373+
d => d.secondaryValue
374+
)
375+
)}
376+
</td>
377+
</tr>
378+
)
379+
})
380+
: null}
369381
</tbody>
370382
</table>
371383
</div>

src/components/Voronoi.tsx

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,13 @@ import { Delaunay } from 'd3-delaunay'
33

44
//
55
import { Datum } from '../types'
6-
import { getPrimary, getX, getY, sortDatums, translate } from '../utils/Utils'
6+
import {
7+
getPrimary,
8+
getX,
9+
getY,
10+
sortDatumsBySecondaryPx,
11+
translate,
12+
} from '../utils/Utils'
713
import useChartContext from '../utils/chartContext'
814
import { line } from 'd3-shape'
915

@@ -67,6 +73,8 @@ function PrimaryVoronoi<TDatum>({
6773
datumsByInteractionGroup,
6874
} = useChartContext<TDatum>()
6975

76+
const stackedVoronoi = secondaryAxes.length === 1 && secondaryAxes[0].stacked
77+
7078
return React.useMemo(() => {
7179
const columns = series[0].datums
7280
.filter(datum => {
@@ -115,7 +123,7 @@ function PrimaryVoronoi<TDatum>({
115123
d => d.id === datum.secondaryAxisId
116124
)
117125

118-
if (secondaryAxis?.stacked) {
126+
if (stackedVoronoi) {
119127
let range = secondaryAxis?.scale.range() ?? [0, 0]
120128

121129
let stackData = [datum.stackData?.[0], datum.stackData?.[1]]
@@ -144,7 +152,12 @@ function PrimaryVoronoi<TDatum>({
144152
}
145153
}
146154

147-
const value = secondaryAxis?.scale(datum.secondaryValue) ?? NaN
155+
const value =
156+
secondaryAxis?.scale(
157+
secondaryAxis.stacked
158+
? datum.stackData?.[1]
159+
: datum.secondaryValue
160+
) ?? NaN
148161

149162
let range = secondaryAxis?.scale.range() ?? [0, 0]
150163

@@ -158,15 +171,21 @@ function PrimaryVoronoi<TDatum>({
158171
const prevAxis = secondaryAxes.find(
159172
d => d.id === prev?.secondaryAxisId
160173
)
161-
const prevValue = prevAxis?.scale(prev.secondaryValue) ?? NaN
174+
const prevValue =
175+
prevAxis?.scale(
176+
prevAxis.stacked ? prev.stackData?.[1] : prev.secondaryValue
177+
) ?? NaN
162178
secondaryStart = value - (value - prevValue) / 2
163179
}
164180

165181
if (next) {
166182
const nextAxis = secondaryAxes.find(
167183
d => d.id === next?.secondaryAxisId
168184
)
169-
const nextValue = nextAxis?.scale(next.secondaryValue) ?? NaN
185+
const nextValue =
186+
nextAxis?.scale(
187+
nextAxis.stacked ? next.stackData?.[1] : next.secondaryValue
188+
) ?? NaN
170189
secondaryEnd = value + (nextValue - value) / 2
171190
}
172191

@@ -241,14 +260,15 @@ function PrimaryVoronoi<TDatum>({
241260
</g>
242261
)
243262
}, [
244-
getOptions,
263+
series,
245264
gridDimensions.left,
246265
gridDimensions.top,
247-
datumsByInteractionGroup,
248-
handleFocus,
249266
primaryAxis,
267+
datumsByInteractionGroup,
250268
secondaryAxes,
251-
series,
269+
stackedVoronoi,
270+
handleFocus,
271+
getOptions,
252272
])
253273
}
254274

src/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ export type AxisOptionsBase = {
249249
show?: boolean
250250
stacked?: boolean
251251
stackOffset?: typeof stackOffsetNone
252-
id?: string
252+
id?: string | number
253253
styles?: CSSProperties & {
254254
line?: CSSProperties
255255
tick?: CSSProperties

src/utils/Utils.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ export function getTickPx<TDatum>(scale: Axis<TDatum>['scale'], value: any) {
267267
return px
268268
}
269269

270-
export function sortDatums<TDatum>(
270+
export function sortDatumsBySecondaryPx<TDatum>(
271271
datums: Datum<TDatum>[],
272272
secondaryAxes: Axis<TDatum>[]
273273
) {
@@ -277,6 +277,7 @@ export function sortDatums<TDatum>(
277277

278278
const aPx =
279279
aAxis?.scale(aAxis.stacked ? a.stackData?.[1] : a.secondaryValue) ?? NaN
280+
280281
const bPx =
281282
bAxis?.scale(bAxis.stacked ? b.stackData?.[1] : b.secondaryValue) ?? NaN
282283

0 commit comments

Comments
 (0)