@@ -18,6 +18,34 @@ import {
1818import { selectorChartSeriesProcessed } from '../../corePlugins/useChartSeries/useChartSeries.selectors' ;
1919import { 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+
2149export 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