mirror of
https://github.com/chartjs/Chart.js.git
synced 2026-02-20 01:31:20 +01:00
Bugfix: span gaps over null values beyond scale limits (#11984)
* Bugfix: spanGaps not working near min and max limits * Fix error when meta.dataset.options = null * Add tests for correct setting of line controller properties _drawStart and _drawCount * Fix spacing in controller line tests * Add tension to test * Add a better test case * Avoid the use of FindLastIndex * Avoid taking 0 for null value and improve naming
This commit is contained in:
@@ -91,25 +91,41 @@ export function _getStartAndCountOfVisiblePoints(meta: ChartMeta<'line' | 'scatt
|
||||
let count = pointCount;
|
||||
|
||||
if (meta._sorted) {
|
||||
const {iScale, _parsed} = meta;
|
||||
const {iScale, vScale, _parsed} = meta;
|
||||
const spanGaps = meta.dataset ? meta.dataset.options ? meta.dataset.options.spanGaps : null : null;
|
||||
const axis = iScale.axis;
|
||||
const {min, max, minDefined, maxDefined} = iScale.getUserBounds();
|
||||
|
||||
if (minDefined) {
|
||||
start = _limitValue(Math.min(
|
||||
start = Math.min(
|
||||
// @ts-expect-error Need to type _parsed
|
||||
_lookupByKey(_parsed, axis, min).lo,
|
||||
// @ts-expect-error Need to fix types on _lookupByKey
|
||||
animationsDisabled ? pointCount : _lookupByKey(points, axis, iScale.getPixelForValue(min)).lo),
|
||||
0, pointCount - 1);
|
||||
animationsDisabled ? pointCount : _lookupByKey(points, axis, iScale.getPixelForValue(min)).lo);
|
||||
if (spanGaps) {
|
||||
const distanceToDefinedLo = (_parsed
|
||||
.slice(0, start + 1)
|
||||
.reverse()
|
||||
.findIndex(
|
||||
point => point[vScale.axis] || point[vScale.axis] === 0));
|
||||
start -= Math.max(0, distanceToDefinedLo);
|
||||
}
|
||||
start = _limitValue(start, 0, pointCount - 1);
|
||||
}
|
||||
if (maxDefined) {
|
||||
count = _limitValue(Math.max(
|
||||
let end = Math.max(
|
||||
// @ts-expect-error Need to type _parsed
|
||||
_lookupByKey(_parsed, iScale.axis, max, true).hi + 1,
|
||||
// @ts-expect-error Need to fix types on _lookupByKey
|
||||
animationsDisabled ? 0 : _lookupByKey(points, axis, iScale.getPixelForValue(max), true).hi + 1),
|
||||
start, pointCount) - start;
|
||||
animationsDisabled ? 0 : _lookupByKey(points, axis, iScale.getPixelForValue(max), true).hi + 1);
|
||||
if (spanGaps) {
|
||||
const distanceToDefinedHi = (_parsed
|
||||
.slice(end - 1)
|
||||
.findIndex(
|
||||
point => point[vScale.axis] || point[vScale.axis] === 0));
|
||||
end += Math.max(0, distanceToDefinedHi);
|
||||
}
|
||||
count = _limitValue(end, start, pointCount) - start;
|
||||
} else {
|
||||
count = pointCount - start;
|
||||
}
|
||||
|
||||
@@ -1071,6 +1071,93 @@ describe('Chart.controllers.line', function() {
|
||||
expect(visiblePoints.length).toBe(6);
|
||||
}, 500);
|
||||
|
||||
it('should correctly calc _drawStart and _drawCount when first points beyond scale limits are null and spanGaps=true', async() => {
|
||||
var chart = window.acquireChart({
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: [0, 10, 20, 30, 40, 50],
|
||||
datasets: [{
|
||||
data: [3, null, 2, 3, null, 1.5],
|
||||
spanGaps: true,
|
||||
tension: 0.4
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
scales: {
|
||||
x: {
|
||||
type: 'linear',
|
||||
min: 11,
|
||||
max: 40,
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
chart.update();
|
||||
var controller = chart.getDatasetMeta(0).controller;
|
||||
|
||||
expect(controller._drawStart).toBe(0);
|
||||
expect(controller._drawCount).toBe(6);
|
||||
}, 500);
|
||||
|
||||
it('should correctly calc _drawStart and _drawCount when all points beyond scale limits are null and spanGaps=true', async() => {
|
||||
var chart = window.acquireChart({
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: [0, 10, 20, 30, 40, 50],
|
||||
datasets: [{
|
||||
data: [null, null, 2, 3, null, null],
|
||||
spanGaps: true,
|
||||
tension: 0.4
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
scales: {
|
||||
x: {
|
||||
type: 'linear',
|
||||
min: 11,
|
||||
max: 40,
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
chart.update();
|
||||
var controller = chart.getDatasetMeta(0).controller;
|
||||
|
||||
expect(controller._drawStart).toBe(1);
|
||||
expect(controller._drawCount).toBe(4);
|
||||
}, 500);
|
||||
|
||||
it('should correctly calc _drawStart and _drawCount when spanGaps=false', async() => {
|
||||
var chart = window.acquireChart({
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: [0, 10, 20, 30, 40, 50],
|
||||
datasets: [{
|
||||
data: [3, null, 2, 3, null, 1.5],
|
||||
spanGaps: false,
|
||||
tension: 0.4
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
scales: {
|
||||
x: {
|
||||
type: 'linear',
|
||||
min: 11,
|
||||
max: 40,
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
chart.update();
|
||||
var controller = chart.getDatasetMeta(0).controller;
|
||||
|
||||
expect(controller._drawStart).toBe(1);
|
||||
expect(controller._drawCount).toBe(4);
|
||||
}, 500);
|
||||
|
||||
it('should not override tooltip title and label callbacks', async() => {
|
||||
const chart = window.acquireChart({
|
||||
type: 'line',
|
||||
|
||||
Reference in New Issue
Block a user