Skip to content

Commit c8a5867

Browse files
committed
fix: mixed element voronoi
1 parent 6830ffd commit c8a5867

File tree

6 files changed

+51
-19
lines changed

6 files changed

+51
-19
lines changed

examples/simple/src/ResizableBox.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import "react-resizable/css/styles.css";
55

66
export default function ResizableBox({
77
children,
8-
width = 500,
8+
width = 600,
99
height = 300,
1010
resizable = true,
1111
style = {},

examples/simple/src/components/MultipleAxes.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ import { AxisOptions, Chart } from "react-charts";
55

66
export default function MultipleAxes() {
77
const { data, randomizeData } = useDemoConfig({
8-
series: 10,
8+
series: 6,
99
dataType: "time",
1010
});
1111

1212
// @ts-ignore
13-
data.forEach((d, i) => (d.secondaryAxisId = i % 3 === 0 ? "2" : undefined));
13+
data.forEach((d, i) => (d.secondaryAxisId = i > 2 ? "2" : undefined));
1414

1515
const primaryAxis = React.useMemo<
1616
AxisOptions<typeof data[number]["data"][number]>

src/components/Chart.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,8 @@ function ChartInner<TDatum>({
380380
const series = React.useMemo(() => {
381381
const series: Series<TDatum>[] = []
382382

383+
const indicesByAxisId: Record<string, number> = {}
384+
383385
for (
384386
let seriesIndex = 0;
385387
seriesIndex < options.data.length;
@@ -392,6 +394,12 @@ function ChartInner<TDatum>({
392394
const originalDatums = originalSeries.data
393395
const datums = []
394396

397+
indicesByAxisId[`${secondaryAxisId}`] =
398+
indicesByAxisId[`${secondaryAxisId}`] ?? 0
399+
const seriesIndexPerAxis = indicesByAxisId[`${secondaryAxisId}`]
400+
401+
indicesByAxisId[`${secondaryAxisId}`]++
402+
395403
for (
396404
let datumIndex = 0;
397405
datumIndex < originalDatums.length;
@@ -401,6 +409,7 @@ function ChartInner<TDatum>({
401409
datums[datumIndex] = {
402410
originalSeries,
403411
seriesIndex,
412+
seriesIndexPerAxis,
404413
seriesId,
405414
seriesLabel,
406415
secondaryAxisId,
@@ -414,6 +423,7 @@ function ChartInner<TDatum>({
414423
index: seriesIndex,
415424
id: seriesId,
416425
label: seriesLabel,
426+
indexPerAxis: seriesIndexPerAxis,
417427
secondaryAxisId,
418428
datums,
419429
}
@@ -528,6 +538,7 @@ function ChartInner<TDatum>({
528538
}, [
529539
allDatums,
530540
options.interactionMode,
541+
primaryAxis,
531542
secondaryAxes,
532543
tooltipOptions.groupingMode,
533544
])

src/components/Voronoi.tsx

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ function PrimaryVoronoi<TDatum>({
6969

7070
const stackedVoronoi = secondaryAxes.length === 1 && secondaryAxes[0].stacked
7171

72+
const useBarPx = secondaryAxes.every(
73+
d => d.elementType === 'bar' && !d.stacked
74+
)
75+
7276
return React.useMemo(() => {
7377
let preColumns = Array.from(datumsByInteractionGroup.entries())
7478
.map(([_, datums]) => datums)
@@ -86,8 +90,8 @@ function PrimaryVoronoi<TDatum>({
8690
const aAxis = secondaryAxes.find(d => d.id === a[0].secondaryAxisId)!
8791
const bAxis = secondaryAxes.find(d => d.id === b[0].secondaryAxisId)!
8892

89-
const aPx = getPrimary(a[0], primaryAxis, aAxis)
90-
const bPx = getPrimary(b[0], primaryAxis, bAxis)
93+
const aPx = getPrimary(a[0], primaryAxis, aAxis, useBarPx)
94+
const bPx = getPrimary(b[0], primaryAxis, bAxis, useBarPx)
9195

9296
return aPx - bPx
9397
})
@@ -105,7 +109,7 @@ function PrimaryVoronoi<TDatum>({
105109
const secondaryAxis = secondaryAxes.find(
106110
d => d.id === datum.secondaryAxisId
107111
)!
108-
const primaryPx = getPrimary(datum, primaryAxis, secondaryAxis)
112+
const primaryPx = getPrimary(datum, primaryAxis, secondaryAxis, useBarPx)
109113

110114
let range = primaryAxis?.scale.range() ?? [0, 0]
111115

@@ -115,15 +119,15 @@ function PrimaryVoronoi<TDatum>({
115119
const secondaryAxis = secondaryAxes.find(
116120
d => d.id === prev[0].secondaryAxisId
117121
)!
118-
const prevPx = getPrimary(prev[0], primaryAxis, secondaryAxis)
122+
const prevPx = getPrimary(prev[0], primaryAxis, secondaryAxis, useBarPx)
119123
primaryStart = primaryPx - (primaryPx - prevPx) / 2
120124
}
121125

122126
if (next) {
123127
const secondaryAxis = secondaryAxes.find(
124128
d => d.id === next[0].secondaryAxisId
125129
)!
126-
const nextPx = getPrimary(next[0], primaryAxis, secondaryAxis)
130+
const nextPx = getPrimary(next[0], primaryAxis, secondaryAxis, useBarPx)
127131
primaryEnd = primaryPx + (nextPx - primaryPx) / 2
128132
}
129133

@@ -283,10 +287,11 @@ function PrimaryVoronoi<TDatum>({
283287
)
284288
}, [
285289
datumsByInteractionGroup,
290+
primaryAxis,
286291
gridDimensions.left,
287292
gridDimensions.top,
288293
secondaryAxes,
289-
primaryAxis,
294+
useBarPx,
290295
stackedVoronoi,
291296
handleFocus,
292297
getOptions,
@@ -313,6 +318,10 @@ function SingleVoronoi<TDatum>({
313318

314319
const voronoiData: { x: number; y: number; datum: Datum<TDatum> }[] = []
315320

321+
const useBarPx = secondaryAxes.every(
322+
d => d.elementType === 'bar' && !d.stacked
323+
)
324+
316325
series.forEach(serie => {
317326
serie.datums
318327
.filter(datum => {
@@ -329,8 +338,8 @@ function SingleVoronoi<TDatum>({
329338
const secondaryAxis = secondaryAxes.find(
330339
d => d.id === datum.secondaryAxisId
331340
)
332-
const x = getX(datum, primaryAxis, secondaryAxis!)
333-
const y = getY(datum, primaryAxis, secondaryAxis!)
341+
const x = getX(datum, primaryAxis, secondaryAxis!, useBarPx)
342+
const y = getY(datum, primaryAxis, secondaryAxis!, useBarPx)
334343

335344
if (
336345
typeof x !== 'number' ||
@@ -403,31 +412,34 @@ function SingleVoronoi<TDatum>({
403412
function getX<TDatum>(
404413
datum: Datum<TDatum>,
405414
primaryAxis: Axis<TDatum>,
406-
secondaryAxis: Axis<TDatum>
415+
secondaryAxis: Axis<TDatum>,
416+
useBarPx: boolean
407417
): number {
408418
return primaryAxis.isVertical
409419
? getSecondary(datum, secondaryAxis)
410-
: getPrimary(datum, primaryAxis, secondaryAxis)
420+
: getPrimary(datum, primaryAxis, secondaryAxis, useBarPx)
411421
}
412422

413423
function getY<TDatum>(
414424
datum: Datum<TDatum>,
415425
primaryAxis: Axis<TDatum>,
416-
secondaryAxis: Axis<TDatum>
426+
secondaryAxis: Axis<TDatum>,
427+
useBarPx: boolean
417428
): number {
418429
return primaryAxis.isVertical
419-
? getPrimary(datum, primaryAxis, secondaryAxis)
430+
? getPrimary(datum, primaryAxis, secondaryAxis, useBarPx)
420431
: getSecondary(datum, secondaryAxis)
421432
}
422433

423434
function getPrimary<TDatum>(
424435
datum: Datum<TDatum>,
425436
primaryAxis: Axis<TDatum>,
426-
secondaryAxis: Axis<TDatum>
437+
secondaryAxis: Axis<TDatum>,
438+
useBarPx: boolean
427439
): number {
428440
let primary = primaryAxis.scale(datum.primaryValue) ?? NaN
429441

430-
if (secondaryAxis.elementType === 'bar') {
442+
if (useBarPx && secondaryAxis.elementType === 'bar') {
431443
if (!secondaryAxis.stacked) {
432444
primary += primaryAxis.seriesBandScale!(datum.seriesIndex) ?? NaN
433445
primary += getPrimaryLength(datum, primaryAxis, secondaryAxis) / 2

src/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,7 @@ export type UserSerie<TDatum> = {
436436
export type Series<TDatum> = {
437437
originalSeries: UserSerie<TDatum>
438438
index: number
439+
indexPerAxis: number
439440
id: string
440441
label: string
441442
secondaryAxisId?: string
@@ -451,6 +452,7 @@ export type Datum<TDatum> = {
451452
index: number
452453
originalDatum: TDatum
453454
secondaryAxisId?: string
455+
seriesIndexPerAxis: number
454456
primaryValue?: any
455457
secondaryValue?: any
456458
stackData?: StackDatum<TDatum>

src/utils/buildAxis.linear.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,8 @@ function buildBandAxis<TDatum>(
359359
range: [number, number],
360360
outerRange: [number, number]
361361
): AxisBand<TDatum> {
362+
series = series.filter(d => d.secondaryAxisId === options.id)
363+
362364
const domain = Array.from(
363365
new Set(
364366
series
@@ -524,7 +526,9 @@ function buildSeriesBandScale<TDatum>(
524526
primaryBandScale: ScaleBand<number>,
525527
series: Series<TDatum>[]
526528
) {
527-
const bandDomain = d3Range(series.length)
529+
const bandDomain = d3Range(
530+
series.filter(d => d.secondaryAxisId === options.id).length
531+
)
528532

529533
const seriesBandScale = scaleBand(bandDomain, [
530534
0,
@@ -540,5 +544,8 @@ function buildSeriesBandScale<TDatum>(
540544
(options.innerBandPadding ? options.innerBandPadding / 2 : 0)
541545
)
542546

543-
return seriesBandScale
547+
const scale = (seriesIndex: number) =>
548+
seriesBandScale(series.find(d => d.index === seriesIndex)!?.indexPerAxis)
549+
550+
return Object.assign(scale, seriesBandScale)
544551
}

0 commit comments

Comments
 (0)