Skip to content

Commit b77cf18

Browse files
committed
fixes
1 parent 4f90649 commit b77cf18

2 files changed

Lines changed: 45 additions & 18 deletions

File tree

packages/x-charts/src/internals/plugins/featurePlugins/useChartClosestPoint/findClosestPoints.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,14 @@ export function findClosestPoints(
9191
}
9292
ranked.sort((a, b) => a.edge - b.edge);
9393

94-
// The pointer is inside multiple marks, we sore them by distance to the center.
95-
const splitIndex = ranked.findIndex((d) => d.edge > 0);
94+
// The pointer is inside multiple marks, we sort them by distance to the center. Priority is
95+
// 1. marks that are under the pointer (negative edge distance) sorted by distance to the center
96+
// 2. marks that are outside the pointer (positive edge distance) by distance to the edge
97+
const splitIndex = ranked.findLastIndex((d) => d.edge < 0);
9698
if (splitIndex !== -1) {
9799
ranked = [
98-
...ranked.slice(0, splitIndex).sort((a, b) => a.centerDistSq - b.centerDistSq),
99-
...ranked.slice(splitIndex),
100+
...ranked.slice(0, splitIndex + 1).sort((a, b) => a.centerDistSq - b.centerDistSq),
101+
...ranked.slice(splitIndex + 1),
100102
];
101103
}
102104
return ranked.slice(0, Math.min(ranked.length, maxResults)).map((d) => d.index);

packages/x-charts/src/internals/plugins/featurePlugins/useChartClosestPoint/useChartClosestPoint.ts

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,34 @@ import {
1818
import { selectorChartSeriesProcessed } from '../../corePlugins/useChartSeries/useChartSeries.selectors';
1919
import { findClosestPoints } from './findClosestPoints';
2020

21+
type ClosestPoint = { dataIndex: number; seriesId: SeriesId; edgeDistance: number; radius: number };
22+
23+
/**
24+
* Return `true` if the candidate point is closer to the pointer than the current closest point.
25+
* By priority we prefer:
26+
* 1. points that are under the pointer (negative edge distance) sorted by distance to the center.
27+
* 2. points that are outside the pointer (positive edge distance) by distance to the edge.
28+
*/
29+
function isCloser(candidatePoint: ClosestPoint, currentClosestPoint: ClosestPoint | undefined) {
30+
if (currentClosestPoint === undefined) {
31+
return true;
32+
}
33+
34+
if (candidatePoint.edgeDistance <= 0) {
35+
if (currentClosestPoint.edgeDistance > 0) {
36+
return true;
37+
}
38+
const candidateDistance = candidatePoint.edgeDistance + candidatePoint.radius;
39+
const currentDistance = currentClosestPoint.edgeDistance + currentClosestPoint.radius;
40+
return candidateDistance < currentDistance;
41+
}
42+
if (currentClosestPoint.edgeDistance <= 0) {
43+
return false;
44+
}
45+
46+
return candidatePoint.edgeDistance < currentClosestPoint.edgeDistance;
47+
}
48+
2149
export const useChartClosestPoint: ChartPlugin<UseChartClosestPointSignature> = ({
2250
params,
2351
store,
@@ -65,9 +93,7 @@ export const useChartClosestPoint: ChartPlugin<UseChartClosestPointSignature> =
6593
return 'outside-chart';
6694
}
6795

68-
let closestPoint:
69-
| { dataIndex: number; seriesId: SeriesId; edgeDistance: number }
70-
| undefined = undefined;
96+
let closestPoint: ClosestPoint | undefined = undefined;
7197

7298
for (const seriesId of seriesOrder ?? []) {
7399
const aSeries = (series ?? {})[seriesId];
@@ -123,19 +149,18 @@ export const useChartClosestPoint: ChartPlugin<UseChartClosestPointSignature> =
123149
typeof getItemRadius === 'number' ? getItemRadius : getItemRadius(closestPointIndex);
124150
const edgeDistance = centerDist - closestPointRadius;
125151

126-
if (edgeDistance > closestPointRadius && resolvedHitAreaRadius === 'item') {
152+
if (resolvedHitAreaRadius === 'item' && edgeDistance > 0) {
127153
continue;
128154
}
129-
if (
130-
closestPoint === undefined ||
131-
edgeDistance < closestPoint.edgeDistance ||
132-
(resolvedHitAreaRadius === 'item' && edgeDistance === closestPoint.edgeDistance)
133-
) {
134-
closestPoint = {
135-
dataIndex: closestPointIndex,
136-
seriesId,
137-
edgeDistance,
138-
};
155+
156+
const newPoint = {
157+
dataIndex: closestPointIndex,
158+
seriesId,
159+
edgeDistance,
160+
radius: closestPointRadius,
161+
};
162+
if (isCloser(newPoint, closestPoint)) {
163+
closestPoint = newPoint;
139164
}
140165
}
141166

0 commit comments

Comments
 (0)