From 8303f4b05e26bd066e3f60ec4d7271de6cfec721 Mon Sep 17 00:00:00 2001 From: Jukka Kurkela Date: Thu, 16 Jan 2020 12:29:51 +0200 Subject: [PATCH] Conditionally use binarySearch for intersect mode --- src/core/core.datasetController.js | 4 +++ src/core/core.interaction.js | 49 ++++++++++++++---------------- 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/src/core/core.datasetController.js b/src/core/core.datasetController.js index b0a63f02f48..8a46410d906 100644 --- a/src/core/core.datasetController.js +++ b/src/core/core.datasetController.js @@ -980,6 +980,10 @@ helpers.extend(DatasetController.prototype, { * @private */ _getSharedOptions: function(mode, el, options) { + if (!mode) { + // store element option sharing status for usage in interactions + this._elementsShareOptions = options && options.$shared; + } if (mode !== 'reset' && options && options.$shared && el && el.options && el.options.$shared) { return {target: el.options, options}; } diff --git a/src/core/core.interaction.js b/src/core/core.interaction.js index 05c1382983f..4d0ee5610cb 100644 --- a/src/core/core.interaction.js +++ b/src/core/core.interaction.js @@ -41,36 +41,38 @@ function evaluateAllVisibleItems(chart, handler) { } } +function useBinarySearch(axis, controller, _sorted, intersect) { + const iScale = controller._cachedMeta.iScale; + return iScale && axis === iScale.axis && _sorted && + (!intersect || controller._elementsShareOptions); +} + /** * Helper function to get items using binary search, when the data is sorted. * @param {Chart} chart - the chart * @param {string} axis - the axis mode. x|y|xy * @param {object} position - the point to be nearest to * @param {function} handler - the callback to execute for each visible item - * @return whether all scales were of a suitable type + * @param {boolean} intersect - consider intersecting items */ -function binarySearchItems(chart, axis, position, handler) { +function optimizedEvaluateItems(chart, axis, position, handler, intersect) { const metasets = chart._getSortedVisibleDatasetMetas(); for (let i = 0, ilen = metasets.length; i < ilen; ++i) { - const metaset = metasets[i]; - const iScale = metaset.controller._cachedMeta.iScale; - if (!iScale || axis !== iScale.axis || !metaset._sorted) { - return false; - } - } - - // do this only after checking whether all scales are of a suitable type - for (let i = 0, ilen = metasets.length; i < ilen; ++i) { - const {index, data} = metasets[i]; - const {lo, hi, loIndex, hiIndex} = _lookup(data, axis, position[axis]); - if (lo) { - handler(lo, index, loIndex); + const {controller, data, index, _sorted} = metasets[i]; + let startIndex = 0; + let endIndex = data.length - 1; + if (useBinarySearch(axis, controller, _sorted, intersect)) { + const {loIndex, hiIndex} = _lookup(data, axis, position[axis]); + startIndex = loIndex === null ? hiIndex : loIndex; + endIndex = hiIndex === null ? loIndex : hiIndex; } - if (hi) { - handler(hi, index, hiIndex); + for (let j = startIndex; j <= endIndex; ++j) { + const element = data[j]; + if (!element.skip) { + handler(element, index, j); + } } } - return true; } /** @@ -96,7 +98,7 @@ function getDistanceMetricForAxis(axis) { * @param {string} axis - the axis mode. x|y|xy * @return {ChartElement[]} the nearest items */ -function getIntersectItems(chart, position) { +function getIntersectItems(chart, position, axis) { const items = []; if (!_isPointInArea(position, chart.chartArea)) { @@ -109,7 +111,7 @@ function getIntersectItems(chart, position) { } }; - evaluateAllVisibleItems(chart, evaluationFunc); + optimizedEvaluateItems(chart, axis, position, evaluationFunc, true); return items; } @@ -146,12 +148,7 @@ function getNearestItems(chart, position, axis, intersect) { } }; - const optimized = binarySearchItems(chart, axis, position, evaluationFunc); - if (optimized) { - return items; - } - - evaluateAllVisibleItems(chart, evaluationFunc); + optimizedEvaluateItems(chart, axis, position, evaluationFunc); return items; }