diff --git a/src/component/axisPointer/axisTrigger.ts b/src/component/axisPointer/axisTrigger.ts index e3051b953d..50031bb172 100644 --- a/src/component/axisPointer/axisTrigger.ts +++ b/src/component/axisPointer/axisTrigger.ts @@ -273,7 +273,7 @@ function buildPayloadsBySeries(value: AxisValue, axisInfo: CollectedAxisInfo) { seriesNestestValue = result.nestestValue; } else { - dataIndices = series.getData().indicesOfNearest( + dataIndices = series.indicesOfNearest( dataDim[0], value as number, // Add a threshold to avoid find the wrong dataIndex diff --git a/src/model/Series.ts b/src/model/Series.ts index 94e630fc17..6faab93f93 100644 --- a/src/model/Series.ts +++ b/src/model/Series.ts @@ -30,7 +30,8 @@ import { SeriesEncodeOptionMixin, OptionEncodeValue, ColorBy, - StatesOptionMixin + StatesOptionMixin, + DimensionLoose } from '../util/types'; import ComponentModel, { ComponentModelConstructor } from './Component'; import {PaletteMixin} from './mixin/palette'; @@ -140,7 +141,7 @@ class SeriesModel extends ComponentMode // @readonly type: string; - // Should be implenented in subclass. + // Should be impleneted in subclass. defaultOption: SeriesOption; // @readonly @@ -436,6 +437,60 @@ class SeriesModel extends ComponentMode return coordSys && coordSys.getBaseAxis && coordSys.getBaseAxis(); } + /** + * Retrieve the index of nearest value in the view coordinate. + * Data position is compared with each axis's dataToCoord. + * @param dim + * @param value + * @param [maxDistance=Infinity] + * @return If and only if multiple indices has + * the same value, they are put to the result. + */ + indicesOfNearest(dim: string, value: number, maxDistance?: number): number[] { + const data = this.getData(); + const coordSys = this.coordinateSystem; + const axis = coordSys && coordSys.getAxis(dim); + if (!coordSys || !axis) { + return []; + } + const targetCoord = axis.dataToCoord(value); + + if (maxDistance == null) { + maxDistance = Infinity; + } + + const nearestIndices: number[] = []; + let minDist = Infinity; + let minDiff = -1; + let nearestIndicesLen = 0; + + data.each(dim, (dimValue, idx) => { + const dataCoord = axis.dataToCoord(dimValue); + const diff = targetCoord - dataCoord; + const dist = Math.abs(diff); + if (dist <= maxDistance) { + // When the `value` is at the middle of `this.get(dim, i)` and `this.get(dim, i+1)`, + // we'd better not push both of them to `nearestIndices`, otherwise it is easy to + // get more than one item in `nearestIndices` (more specifically, in `tooltip`). + // So we choose the one that `diff >= 0` in this case. + // But if `this.get(dim, i)` and `this.get(dim, j)` get the same value, both of them + // should be push to `nearestIndices`. + if (dist < minDist + || (dist === minDist && diff >= 0 && minDiff < 0) + ) { + minDist = dist; + minDiff = diff; + nearestIndicesLen = 0; + } + if (diff === minDiff) { + nearestIndices[nearestIndicesLen++] = idx; + } + } + }); + nearestIndices.length = nearestIndicesLen; + return nearestIndices; + } + /** * Default tooltip formatter *