mirror of
https://github.com/chartjs/Chart.js.git
synced 2024-10-06 12:19:08 +02:00
Make index mode only work with the horizontal distance to an element (#3471)
Make index mode only work with the horizontal distance to an element if intersect is off
This commit is contained in:
parent
a86c47cf48
commit
6ec6a929f0
@ -50,19 +50,24 @@ module.exports = function(Chart) {
|
||||
* @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
|
||||
* @return {ChartElement[]} the nearest items
|
||||
*/
|
||||
function getNearestItems(chart, position, intersect) {
|
||||
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;
|
||||
}
|
||||
|
||||
var center = element.getCenterPoint();
|
||||
var distance = Math.round(helpers.distanceBetweenPoints(position, center));
|
||||
var distance = distanceMetric(position, center);
|
||||
|
||||
if (distance < minDistance) {
|
||||
nearestItems = [element];
|
||||
@ -78,7 +83,10 @@ module.exports = function(Chart) {
|
||||
|
||||
function indexMode(chart, e, options) {
|
||||
var position = helpers.getRelativePosition(e, chart.chart);
|
||||
var items = options.intersect ? getIntersectItems(chart, position) : getNearestItems(chart, position, false);
|
||||
var distanceMetric = function(pt1, pt2) {
|
||||
return Math.abs(pt1.x - pt2.x);
|
||||
};
|
||||
var items = options.intersect ? getIntersectItems(chart, position) : getNearestItems(chart, position, false, distanceMetric);
|
||||
var elements = [];
|
||||
|
||||
if (!items.length) {
|
||||
|
@ -1,118 +1,209 @@
|
||||
// Test the rectangle element
|
||||
describe('tooltip tests', function() {
|
||||
it('Should display in label mode', function() {
|
||||
var chartInstance = window.acquireChart({
|
||||
type: 'line',
|
||||
data: {
|
||||
datasets: [{
|
||||
label: 'Dataset 1',
|
||||
data: [10, 20, 30],
|
||||
pointHoverBorderColor: 'rgb(255, 0, 0)',
|
||||
pointHoverBackgroundColor: 'rgb(0, 255, 0)'
|
||||
}, {
|
||||
label: 'Dataset 2',
|
||||
data: [40, 40, 40],
|
||||
pointHoverBorderColor: 'rgb(0, 0, 255)',
|
||||
pointHoverBackgroundColor: 'rgb(0, 255, 255)'
|
||||
}],
|
||||
labels: ['Point 1', 'Point 2', 'Point 3']
|
||||
},
|
||||
options: {
|
||||
tooltips: {
|
||||
mode: 'label'
|
||||
describe('Core.Tooltip', function() {
|
||||
describe('index mode', function() {
|
||||
it('Should only use x distance when intersect is false', function() {
|
||||
var chartInstance = window.acquireChart({
|
||||
type: 'line',
|
||||
data: {
|
||||
datasets: [{
|
||||
label: 'Dataset 1',
|
||||
data: [10, 20, 30],
|
||||
pointHoverBorderColor: 'rgb(255, 0, 0)',
|
||||
pointHoverBackgroundColor: 'rgb(0, 255, 0)'
|
||||
}, {
|
||||
label: 'Dataset 2',
|
||||
data: [40, 40, 40],
|
||||
pointHoverBorderColor: 'rgb(0, 0, 255)',
|
||||
pointHoverBackgroundColor: 'rgb(0, 255, 255)'
|
||||
}],
|
||||
labels: ['Point 1', 'Point 2', 'Point 3']
|
||||
},
|
||||
options: {
|
||||
tooltips: {
|
||||
mode: 'index',
|
||||
intersect: false
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Trigger an event over top of the
|
||||
var meta = chartInstance.getDatasetMeta(0);
|
||||
var point = meta.data[1];
|
||||
|
||||
var node = chartInstance.chart.canvas;
|
||||
var rect = node.getBoundingClientRect();
|
||||
|
||||
var evt = new MouseEvent('mousemove', {
|
||||
view: window,
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
clientX: rect.left + point._model.x,
|
||||
clientY: 0
|
||||
});
|
||||
|
||||
// Manully trigger rather than having an async test
|
||||
node.dispatchEvent(evt);
|
||||
|
||||
// Check and see if tooltip was displayed
|
||||
var tooltip = chartInstance.tooltip;
|
||||
var globalDefaults = Chart.defaults.global;
|
||||
|
||||
expect(tooltip._view).toEqual(jasmine.objectContaining({
|
||||
// Positioning
|
||||
xPadding: 6,
|
||||
yPadding: 6,
|
||||
xAlign: 'left',
|
||||
yAlign: 'center',
|
||||
|
||||
// Body
|
||||
bodyFontColor: '#fff',
|
||||
_bodyFontFamily: globalDefaults.defaultFontFamily,
|
||||
_bodyFontStyle: globalDefaults.defaultFontStyle,
|
||||
_bodyAlign: 'left',
|
||||
bodyFontSize: globalDefaults.defaultFontSize,
|
||||
bodySpacing: 2,
|
||||
|
||||
// Title
|
||||
titleFontColor: '#fff',
|
||||
_titleFontFamily: globalDefaults.defaultFontFamily,
|
||||
_titleFontStyle: 'bold',
|
||||
titleFontSize: globalDefaults.defaultFontSize,
|
||||
_titleAlign: 'left',
|
||||
titleSpacing: 2,
|
||||
titleMarginBottom: 6,
|
||||
|
||||
// Footer
|
||||
footerFontColor: '#fff',
|
||||
_footerFontFamily: globalDefaults.defaultFontFamily,
|
||||
_footerFontStyle: 'bold',
|
||||
footerFontSize: globalDefaults.defaultFontSize,
|
||||
_footerAlign: 'left',
|
||||
footerSpacing: 2,
|
||||
footerMarginTop: 6,
|
||||
|
||||
// Appearance
|
||||
caretSize: 5,
|
||||
cornerRadius: 6,
|
||||
backgroundColor: 'rgba(0,0,0,0.8)',
|
||||
opacity: 1,
|
||||
legendColorBackground: '#fff',
|
||||
displayColors: true,
|
||||
|
||||
// Text
|
||||
title: ['Point 2'],
|
||||
beforeBody: [],
|
||||
body: [{
|
||||
before: [],
|
||||
lines: ['Dataset 1: 20'],
|
||||
after: []
|
||||
}, {
|
||||
before: [],
|
||||
lines: ['Dataset 2: 40'],
|
||||
after: []
|
||||
}],
|
||||
afterBody: [],
|
||||
footer: [],
|
||||
caretPadding: 2,
|
||||
labelColors: [{
|
||||
borderColor: 'rgb(255, 0, 0)',
|
||||
backgroundColor: 'rgb(0, 255, 0)'
|
||||
}, {
|
||||
borderColor: 'rgb(0, 0, 255)',
|
||||
backgroundColor: 'rgb(0, 255, 255)'
|
||||
}]
|
||||
}));
|
||||
|
||||
expect(tooltip._view.x).toBeCloseToPixel(269);
|
||||
expect(tooltip._view.y).toBeCloseToPixel(155);
|
||||
});
|
||||
|
||||
// Trigger an event over top of the
|
||||
var meta = chartInstance.getDatasetMeta(0);
|
||||
var point = meta.data[1];
|
||||
it('Should only display if intersecting if intersect is set', function() {
|
||||
var chartInstance = window.acquireChart({
|
||||
type: 'line',
|
||||
data: {
|
||||
datasets: [{
|
||||
label: 'Dataset 1',
|
||||
data: [10, 20, 30],
|
||||
pointHoverBorderColor: 'rgb(255, 0, 0)',
|
||||
pointHoverBackgroundColor: 'rgb(0, 255, 0)'
|
||||
}, {
|
||||
label: 'Dataset 2',
|
||||
data: [40, 40, 40],
|
||||
pointHoverBorderColor: 'rgb(0, 0, 255)',
|
||||
pointHoverBackgroundColor: 'rgb(0, 255, 255)'
|
||||
}],
|
||||
labels: ['Point 1', 'Point 2', 'Point 3']
|
||||
},
|
||||
options: {
|
||||
tooltips: {
|
||||
mode: 'index',
|
||||
intersect: true
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var node = chartInstance.chart.canvas;
|
||||
var rect = node.getBoundingClientRect();
|
||||
// Trigger an event over top of the
|
||||
var meta = chartInstance.getDatasetMeta(0);
|
||||
var point = meta.data[1];
|
||||
|
||||
var evt = new MouseEvent('mousemove', {
|
||||
view: window,
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
clientX: rect.left + point._model.x,
|
||||
clientY: rect.top + point._model.y
|
||||
var node = chartInstance.chart.canvas;
|
||||
var rect = node.getBoundingClientRect();
|
||||
|
||||
var evt = new MouseEvent('mousemove', {
|
||||
view: window,
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
clientX: rect.left + point._model.x,
|
||||
clientY: 0
|
||||
});
|
||||
|
||||
// Manully trigger rather than having an async test
|
||||
node.dispatchEvent(evt);
|
||||
|
||||
// Check and see if tooltip was displayed
|
||||
var tooltip = chartInstance.tooltip;
|
||||
var globalDefaults = Chart.defaults.global;
|
||||
|
||||
expect(tooltip._view).toEqual(jasmine.objectContaining({
|
||||
// Positioning
|
||||
xPadding: 6,
|
||||
yPadding: 6,
|
||||
|
||||
// Body
|
||||
bodyFontColor: '#fff',
|
||||
_bodyFontFamily: globalDefaults.defaultFontFamily,
|
||||
_bodyFontStyle: globalDefaults.defaultFontStyle,
|
||||
_bodyAlign: 'left',
|
||||
bodyFontSize: globalDefaults.defaultFontSize,
|
||||
bodySpacing: 2,
|
||||
|
||||
// Title
|
||||
titleFontColor: '#fff',
|
||||
_titleFontFamily: globalDefaults.defaultFontFamily,
|
||||
_titleFontStyle: 'bold',
|
||||
titleFontSize: globalDefaults.defaultFontSize,
|
||||
_titleAlign: 'left',
|
||||
titleSpacing: 2,
|
||||
titleMarginBottom: 6,
|
||||
|
||||
// Footer
|
||||
footerFontColor: '#fff',
|
||||
_footerFontFamily: globalDefaults.defaultFontFamily,
|
||||
_footerFontStyle: 'bold',
|
||||
footerFontSize: globalDefaults.defaultFontSize,
|
||||
_footerAlign: 'left',
|
||||
footerSpacing: 2,
|
||||
footerMarginTop: 6,
|
||||
|
||||
// Appearance
|
||||
caretSize: 5,
|
||||
cornerRadius: 6,
|
||||
backgroundColor: 'rgba(0,0,0,0.8)',
|
||||
opacity: 0,
|
||||
legendColorBackground: '#fff',
|
||||
displayColors: true,
|
||||
}));
|
||||
});
|
||||
|
||||
// Manully trigger rather than having an async test
|
||||
node.dispatchEvent(evt);
|
||||
|
||||
// Check and see if tooltip was displayed
|
||||
var tooltip = chartInstance.tooltip;
|
||||
var globalDefaults = Chart.defaults.global;
|
||||
|
||||
expect(tooltip._view).toEqual(jasmine.objectContaining({
|
||||
// Positioning
|
||||
xPadding: 6,
|
||||
yPadding: 6,
|
||||
xAlign: 'left',
|
||||
yAlign: 'center',
|
||||
|
||||
// Body
|
||||
bodyFontColor: '#fff',
|
||||
_bodyFontFamily: globalDefaults.defaultFontFamily,
|
||||
_bodyFontStyle: globalDefaults.defaultFontStyle,
|
||||
_bodyAlign: 'left',
|
||||
bodyFontSize: globalDefaults.defaultFontSize,
|
||||
bodySpacing: 2,
|
||||
|
||||
// Title
|
||||
titleFontColor: '#fff',
|
||||
_titleFontFamily: globalDefaults.defaultFontFamily,
|
||||
_titleFontStyle: 'bold',
|
||||
titleFontSize: globalDefaults.defaultFontSize,
|
||||
_titleAlign: 'left',
|
||||
titleSpacing: 2,
|
||||
titleMarginBottom: 6,
|
||||
|
||||
// Footer
|
||||
footerFontColor: '#fff',
|
||||
_footerFontFamily: globalDefaults.defaultFontFamily,
|
||||
_footerFontStyle: 'bold',
|
||||
footerFontSize: globalDefaults.defaultFontSize,
|
||||
_footerAlign: 'left',
|
||||
footerSpacing: 2,
|
||||
footerMarginTop: 6,
|
||||
|
||||
// Appearance
|
||||
caretSize: 5,
|
||||
cornerRadius: 6,
|
||||
backgroundColor: 'rgba(0,0,0,0.8)',
|
||||
opacity: 1,
|
||||
legendColorBackground: '#fff',
|
||||
displayColors: true,
|
||||
|
||||
// Text
|
||||
title: ['Point 2'],
|
||||
beforeBody: [],
|
||||
body: [{
|
||||
before: [],
|
||||
lines: ['Dataset 1: 20'],
|
||||
after: []
|
||||
}, {
|
||||
before: [],
|
||||
lines: ['Dataset 2: 40'],
|
||||
after: []
|
||||
}],
|
||||
afterBody: [],
|
||||
footer: [],
|
||||
caretPadding: 2,
|
||||
labelColors: [{
|
||||
borderColor: 'rgb(255, 0, 0)',
|
||||
backgroundColor: 'rgb(0, 255, 0)'
|
||||
}, {
|
||||
borderColor: 'rgb(0, 0, 255)',
|
||||
backgroundColor: 'rgb(0, 255, 255)'
|
||||
}]
|
||||
}));
|
||||
|
||||
expect(tooltip._view.x).toBeCloseToPixel(269);
|
||||
expect(tooltip._view.y).toBeCloseToPixel(155);
|
||||
});
|
||||
|
||||
it('Should display in single mode', function() {
|
||||
|
Loading…
Reference in New Issue
Block a user