mirror of
https://github.com/chartjs/Chart.js.git
synced 2024-10-06 12:19:08 +02:00
Avoid tooltip truncation in x axis if there is enough space (#3998)
* In tooltip x align calculation take into account caretSize Truncation up to caretSize pixels could happen if label text produced tooltip element with size width: * left side tooltip: width < x and width > x - caretSize * right side tooltip: width < chartWidth - x and width > chartWidth - x - caretSize Default caretSize = 5, so with default configuration truncation up to 5 pixels could happen. * avoid tooltip truncation if possible use whole chart area for displaying tooltip * in xAlign calculation take into account caretPadding * add tests for tooltip truncation avoid logic * use caretX instead of xCaret * fix lint errors
This commit is contained in:
parent
939756c260
commit
683e86e549
@ -299,10 +299,10 @@ module.exports = function(Chart) {
|
||||
}
|
||||
|
||||
olf = function(x) {
|
||||
return x + size.width > chart.width;
|
||||
return x + size.width + model.caretSize + model.caretPadding > chart.width;
|
||||
};
|
||||
orf = function(x) {
|
||||
return x - size.width < 0;
|
||||
return x - size.width - model.caretSize - model.caretPadding < 0;
|
||||
};
|
||||
yf = function(y) {
|
||||
return y <= midY ? 'top' : 'bottom';
|
||||
@ -336,7 +336,7 @@ module.exports = function(Chart) {
|
||||
/**
|
||||
* @Helper to get the location a tooltip needs to be placed at given the initial position (via the vm) and the size and alignment
|
||||
*/
|
||||
function getBackgroundPoint(vm, size, alignment) {
|
||||
function getBackgroundPoint(vm, size, alignment, chart) {
|
||||
// Background Position
|
||||
var x = vm.x;
|
||||
var y = vm.y;
|
||||
@ -353,6 +353,12 @@ module.exports = function(Chart) {
|
||||
x -= size.width;
|
||||
} else if (xAlign === 'center') {
|
||||
x -= (size.width / 2);
|
||||
if (x + size.width > chart.width) {
|
||||
x = chart.width - size.width;
|
||||
}
|
||||
if (x < 0) {
|
||||
x = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (yAlign === 'top') {
|
||||
@ -545,7 +551,7 @@ module.exports = function(Chart) {
|
||||
tooltipSize = getTooltipSize(this, model);
|
||||
alignment = determineAlignment(this, tooltipSize);
|
||||
// Final Size and Position
|
||||
backgroundPoint = getBackgroundPoint(model, tooltipSize, alignment);
|
||||
backgroundPoint = getBackgroundPoint(model, tooltipSize, alignment, me._chart);
|
||||
} else {
|
||||
model.opacity = 0;
|
||||
}
|
||||
@ -617,7 +623,7 @@ module.exports = function(Chart) {
|
||||
x1 = x2 - caretSize;
|
||||
x3 = x2 + caretSize;
|
||||
} else {
|
||||
x2 = ptX + (width / 2);
|
||||
x2 = vm.caretX;
|
||||
x1 = x2 - caretSize;
|
||||
x3 = x2 + caretSize;
|
||||
}
|
||||
|
@ -882,4 +882,71 @@ describe('Core.Tooltip', function() {
|
||||
expect(fn.calls.first().object instanceof Chart.Tooltip).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
it('Should avoid tooltip truncation in x axis if there is enough space to show tooltip without truncation', function() {
|
||||
var chart = window.acquireChart({
|
||||
type: 'pie',
|
||||
data: {
|
||||
datasets: [{
|
||||
data: [
|
||||
50,
|
||||
50
|
||||
],
|
||||
backgroundColor: [
|
||||
'rgb(255, 0, 0)',
|
||||
'rgb(0, 255, 0)'
|
||||
],
|
||||
label: 'Dataset 1'
|
||||
}],
|
||||
labels: [
|
||||
'Red long tooltip text to avoid unnecessary loop steps',
|
||||
'Green long tooltip text to avoid unnecessary loop steps'
|
||||
]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
animation: {
|
||||
// without this slice center point is calculated wrong
|
||||
animateRotate: false
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Trigger an event over top of the slice
|
||||
for (var slice = 0; slice < 2; slice++) {
|
||||
var meta = chart.getDatasetMeta(0);
|
||||
var point = meta.data[slice].getCenterPoint();
|
||||
var tooltipPosition = meta.data[slice].tooltipPosition();
|
||||
var node = chart.canvas;
|
||||
var rect = node.getBoundingClientRect();
|
||||
|
||||
var mouseMoveEvent = new MouseEvent('mousemove', {
|
||||
view: window,
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
clientX: rect.left + point.x,
|
||||
clientY: rect.top + point.y
|
||||
});
|
||||
var mouseOutEvent = new MouseEvent('mouseout');
|
||||
|
||||
// Lets cycle while tooltip is narrower than chart area
|
||||
var infiniteCycleDefense = 70;
|
||||
for (var i = 0; i < infiniteCycleDefense; i++) {
|
||||
chart.config.data.labels[slice] = chart.config.data.labels[slice] + 'l';
|
||||
chart.update();
|
||||
node.dispatchEvent(mouseOutEvent);
|
||||
node.dispatchEvent(mouseMoveEvent);
|
||||
var model = chart.tooltip._model;
|
||||
expect(model.x).toBeGreaterThanOrEqual(0);
|
||||
if (model.width <= chart.width) {
|
||||
expect(model.x + model.width).toBeLessThanOrEqual(chart.width);
|
||||
}
|
||||
expect(model.caretX).toBe(tooltipPosition.x);
|
||||
// if tooltip is longer than chart area then all tests done
|
||||
if (model.width > chart.width) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user