Skip to content

Commit

Permalink
index-y interaction mode + convert horizontal bar defaults to new mode (
Browse files Browse the repository at this point in the history
#4458)

index-y interaction mode + convert horizontal bar defaults to new mode
  • Loading branch information
etimberg committed Jul 28, 2017
1 parent 2cc242d commit 326991c
Show file tree
Hide file tree
Showing 6 changed files with 556 additions and 575 deletions.
1 change: 1 addition & 0 deletions docs/general/interactions/README.md
Expand Up @@ -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.
17 changes: 16 additions & 1 deletion docs/general/interactions/modes.md
Expand Up @@ -41,7 +41,7 @@ Finds the first item that intersects the point and returns it. Behaves like 'nea
See `'index'` mode

## index
Finds item at the same index. 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 is used to determine the index.
Finds item at the same index. 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 x direction, is used to determine the index.

```javascript
var chart = new Chart(ctx, {
Expand All @@ -55,6 +55,21 @@ var chart = new Chart(ctx, {
})
```

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: 'horizontalBar',
data: data,
options: {
tooltips: {
mode: 'index',
axis: 'y'
}
}
})
```

## x-axis (deprecated)
Behaves like `'index'` mode with `intersect = false`.

Expand Down
7 changes: 5 additions & 2 deletions src/controllers/controller.bar.js
Expand Up @@ -31,7 +31,8 @@ defaults._set('bar', {

defaults._set('horizontalBar', {
hover: {
mode: 'label'
mode: 'index',
axis: 'y'
},

scales: {
Expand Down Expand Up @@ -82,7 +83,9 @@ defaults._set('horizontalBar', {
var datasetLabel = data.datasets[item.datasetIndex].label || '';
return datasetLabel + ': ' + item.xLabel;
}
}
},
mode: 'index',
axis: 'y'
}
});

Expand Down
38 changes: 27 additions & 11 deletions src/core/core.interaction.js
Expand Up @@ -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;
Expand All @@ -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 = [];

Expand Down Expand Up @@ -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;
Expand All @@ -201,7 +215,7 @@ module.exports = {
* @private
*/
'x-axis': function(chart, e) {
return indexMode(chart, e, true);
return indexMode(chart, e, {intersect: true});
},

/**
Expand All @@ -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) {
Expand Down

0 comments on commit 326991c

Please sign in to comment.