From de1cc57d9cde97109b2404c24197f00223f0f09c Mon Sep 17 00:00:00 2001 From: etimberg Date: Sun, 23 Jul 2017 09:26:23 -0400 Subject: [PATCH] Add new axis option to interaction settings. --- docs/general/interactions/README.md | 1 + docs/general/interactions/modes.md | 8 +++--- src/controllers/controller.bar.js | 7 ++++-- src/core/core.interaction.js | 38 ++++++++++++++++++++--------- test/specs/core.tooltip.tests.js | 4 +++ 5 files changed, 41 insertions(+), 17 deletions(-) diff --git a/docs/general/interactions/README.md b/docs/general/interactions/README.md index 1ff1d55d8f7..585e6558204 100644 --- a/docs/general/interactions/README.md +++ b/docs/general/interactions/README.md @@ -6,4 +6,5 @@ The hover configuration is passed into the `options.hover` namespace. The global | ---- | ---- | ------- | ----------- | `mode` | `String` | `'nearest'` | Sets which elements appear in the tooltip. See [Interaction Modes](./modes.md#interaction-modes) for details. | `intersect` | `Boolean` | `true` | if true, the hover mode only applies when the mouse position intersects an item on the chart. +| `axis` | `String` | `'x'` | Can be set to `'x'`, `'y'`, or `'xy'` to define which directions are used in calculating distances. Defaults to `'x'` for `index` mode and `'xy'` in `dataset` and `nearest` modes. | `animationDuration` | `Number` | `400` | Duration in milliseconds it takes to animate hover style changes. \ No newline at end of file diff --git a/docs/general/interactions/modes.md b/docs/general/interactions/modes.md index 3537e1a556d..a46f047e70b 100644 --- a/docs/general/interactions/modes.md +++ b/docs/general/interactions/modes.md @@ -55,16 +55,16 @@ var chart = new Chart(ctx, { }) ``` -## index-y -Finds the item at the same index along the Y axis. If the `intersect` setting is true, the first intersecting item is used to determine the index in the data. If `intersect` false the nearest item, in the y direction, is used to determine the index. +To use index mode in a chart like the horizontal bar chart, where we search along the y direction, you can use the `axis` setting introduced in v2.7.0. By setting this value to `'y'` on the y direction is used. ```javascript var chart = new Chart(ctx, { - type: 'line', + type: 'horizontalBar', data: data, options: { tooltips: { - mode: 'index-y' + mode: 'index', + axis: 'y' } } }) diff --git a/src/controllers/controller.bar.js b/src/controllers/controller.bar.js index dc410e97f80..5cc626809ad 100644 --- a/src/controllers/controller.bar.js +++ b/src/controllers/controller.bar.js @@ -31,7 +31,8 @@ defaults._set('bar', { defaults._set('horizontalBar', { hover: { - mode: 'label' + mode: 'index', + axis: 'y' }, scales: { @@ -82,7 +83,9 @@ defaults._set('horizontalBar', { var datasetLabel = data.datasets[item.datasetIndex].label || ''; return datasetLabel + ': ' + item.xLabel; } - } + }, + mode: 'index', + axis: 'y' } }); diff --git a/src/core/core.interaction.js b/src/core/core.interaction.js index 793468d43fb..4537269529c 100644 --- a/src/core/core.interaction.js +++ b/src/core/core.interaction.js @@ -66,17 +66,13 @@ function getIntersectItems(chart, position) { * @param chart {Chart} the chart to look at elements from * @param position {Point} the point to be nearest to * @param intersect {Boolean} if true, only consider items that intersect the position - * @param distanceMetric {Function} Optional function to provide the distance between + * @param distanceMetric {Function} function to provide the distance between points * @return {ChartElement[]} the nearest items */ function getNearestItems(chart, position, intersect, distanceMetric) { var minDistance = Number.POSITIVE_INFINITY; var nearestItems = []; - if (!distanceMetric) { - distanceMetric = helpers.distanceBetweenPoints; - } - parseVisibleItems(chart, function(element) { if (intersect && !element.inRange(position.x, position.y)) { return; @@ -97,11 +93,27 @@ function getNearestItems(chart, position, intersect, distanceMetric) { return nearestItems; } +/** + * Get a distance metric function for two points based on the + * axis mode setting + * @param {String} axis the axis mode. x|y|xy + */ +function getDistanceMetricForAxis(axis) { + var useX = axis.indexOf('x') !== -1; + var useY = axis.indexOf('y') !== -1; + + return function(pt1, pt2) { + var deltaX = useX ? Math.abs(pt1.x - pt2.x) : 0; + var deltaY = useY ? Math.abs(pt1.y - pt2.y) : 0; + return Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2)); + }; +} + function indexMode(chart, e, options) { var position = getRelativePosition(e, chart); - var distanceMetric = function(pt1, pt2) { - return Math.abs(pt1.x - pt2.x); - }; + // Default axis for index mode is 'x' to match old behaviour + options.axis = options.axis || 'x'; + var distanceMetric = getDistanceMetricForAxis(options.axis); var items = options.intersect ? getIntersectItems(chart, position) : getNearestItems(chart, position, false, distanceMetric); var elements = []; @@ -185,7 +197,9 @@ module.exports = { */ dataset: function(chart, e, options) { var position = getRelativePosition(e, chart); - var items = options.intersect ? getIntersectItems(chart, position) : getNearestItems(chart, position, false); + options.axis = options.axis || 'xy'; + var distanceMetric = getDistanceMetricForAxis(options.axis); + var items = options.intersect ? getIntersectItems(chart, position) : getNearestItems(chart, position, false, distanceMetric); if (items.length > 0) { items = chart.getDatasetMeta(items[0]._datasetIndex).data; @@ -201,7 +215,7 @@ module.exports = { * @private */ 'x-axis': function(chart, e) { - return indexMode(chart, e, true); + return indexMode(chart, e, {intersect: true}); }, /** @@ -227,7 +241,9 @@ module.exports = { */ nearest: function(chart, e, options) { var position = getRelativePosition(e, chart); - var nearestItems = getNearestItems(chart, position, options.intersect); + options.axis = options.axis || 'xy'; + var distanceMetric = getDistanceMetricForAxis(options.axis); + var nearestItems = getNearestItems(chart, position, options.intersect, distanceMetric); // We have multiple items at the same distance from the event. Now sort by smallest if (nearestItems.length > 1) { diff --git a/test/specs/core.tooltip.tests.js b/test/specs/core.tooltip.tests.js index 0fbc46799b5..b1896da3338 100755 --- a/test/specs/core.tooltip.tests.js +++ b/test/specs/core.tooltip.tests.js @@ -46,6 +46,10 @@ describe('Core.Tooltip', function() { }, options: { tooltips: { + mode: 'index', + intersect: false, + }, + hover: { mode: 'index', intersect: false }