Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ export function pan(chart, delta, enabledScales, transition = 'none') {

export function getInitialScaleBounds(chart) {
const state = getState(chart);
storeOriginalScaleLimits(chart, state);
const scaleBounds = {};
for (const scaleId of Object.keys(chart.scales)) {
const {min, max} = state.originalScaleLimits[scaleId] || {min: {}, max: {}};
Expand Down
29 changes: 11 additions & 18 deletions src/scale.types.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,24 +47,17 @@ export function updateRange(scale, {min, max}, limits, zoom = false) {
const minLimit = getLimit(state, scale, scaleLimits, 'min', -Infinity);
const maxLimit = getLimit(state, scale, scaleLimits, 'max', Infinity);

const cmin = Math.max(min, minLimit);
const cmax = Math.min(max, maxLimit);
const range = zoom ? Math.max(cmax - cmin, minRange) : scale.max - scale.min;
if (cmax - cmin !== range) {
if (minLimit > cmax - range) {
min = cmin;
max = cmin + range;
} else if (maxLimit < cmin + range) {
max = cmax;
min = cmax - range;
} else {
const offset = (range - cmax + cmin) / 2;
min = cmin - offset;
max = cmax + offset;
}
} else {
min = cmin;
max = cmax;
const range = zoom ? Math.max(max - min, minRange) : scale.max - scale.min;
const offset = (range - max + min) / 2;
min -= offset;
max += offset;

if (min < minLimit) {
min = minLimit;
max = Math.min(minLimit + range, maxLimit);
} else if (max > maxLimit) {
max = maxLimit;
min = Math.max(maxLimit - range, minLimit);
}
scaleOpts.min = min;
scaleOpts.max = max;
Expand Down
155 changes: 155 additions & 0 deletions test/specs/api.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,107 @@ describe('api', function() {
expect(chart.scales.y.min).toBe(0);
expect(chart.scales.y.max).toBe(100);
});

it('should honor fitted scale updates on reset', function() {
const chart = window.acquireChart({
type: 'scatter',
data: {
datasets: [
{
data: [
{x: 0, y: 0},
{x: 100, y: 100}
]
}
]
}
});

chart.zoom(1.5);
chart.data.datasets[0].data[0].x = -100;
chart.update();
chart.resetZoom();
expect(chart.scales.x.min).toBe(-100);
expect(chart.scales.x.max).toBe(100);
});

it('should no-op with fully constrained limits', function() {
const chart = window.acquireChart({
type: 'scatter',
options: {
scales: {
x: {
min: 0,
max: 100
},
y: {
min: 0,
max: 100
}
},
plugins: {
zoom: {
limits: {
x: {
min: 0,
max: 100,
minRange: 100
}
}
}
}
}
});

chart.zoom(1.5);
expect(chart.scales.x.min).toBe(0);
expect(chart.scales.x.max).toBe(100);
});

it('should honor zoom changes against a limit', function() {
const chart = window.acquireChart({
type: 'scatter',
options: {
scales: {
x: {
min: 0,
max: 100
},
y: {
min: 0,
max: 100
}
},
plugins: {
zoom: {
limits: {
x: {
min: 0,
max: 100
}
}
}
}
}
});
chart.zoom({
x: 1.99,
focalPoint: {
x: chart.scales.x.getPixelForValue(0)
}
});
expect(chart.scales.x.min).toBe(0);
expect(chart.scales.x.max).toBe(1);

chart.zoom({
x: -98,
focalPoint: {
x: chart.scales.x.getPixelForValue(1)
}
});
expect(chart.scales.x.min).toBe(0);
expect(chart.scales.x.max).toBe(100);
});
});

describe('getInitialScaleBounds', function() {
Expand Down Expand Up @@ -123,6 +224,35 @@ describe('api', function() {
expect(chart.getInitialScaleBounds().y.min).toBe(0);
expect(chart.getInitialScaleBounds().y.max).toBe(100);
});

it('should provide updated scale bounds upon data update', function() {
const chart = window.acquireChart({
type: 'scatter',
data: {
datasets: [
{
data: [
{x: 0, y: 0},
{x: 100, y: 100}
]
}
]
}
});

expect(chart.getInitialScaleBounds().x.min).toBe(0);
expect(chart.getInitialScaleBounds().x.max).toBe(100);
expect(chart.getInitialScaleBounds().y.min).toBe(0);
expect(chart.getInitialScaleBounds().y.max).toBe(100);

chart.data.datasets[0].data[0].x = -100;
chart.update();

expect(chart.getInitialScaleBounds().x.min).toBe(-100);
expect(chart.getInitialScaleBounds().x.max).toBe(100);
expect(chart.getInitialScaleBounds().y.min).toBe(0);
expect(chart.getInitialScaleBounds().y.max).toBe(100);
});
});

describe('isZoomedOrPanned', function() {
Expand Down Expand Up @@ -186,5 +316,30 @@ describe('api', function() {
chart.resetZoom();
expect(chart.isZoomedOrPanned()).toBe(false);
});

it('should work with updated data and fitted scales', function() {
const chart = window.acquireChart({
type: 'scatter',
data: {
datasets: [
{
data: [
{x: 0, y: 0},
{x: 100, y: 100}
]
}
]
}
});

// This sequence of operations captures a previous bug.
chart.zoom(1.5);
chart.data.datasets[0].data[0].x = -100;
chart.update();
chart.resetZoom();
expect(chart.scales.x.min).toBe(-100);
expect(chart.scales.x.max).toBe(100);
expect(chart.isZoomedOrPanned()).toBe(false);
});
});
});
2 changes: 1 addition & 1 deletion test/specs/zoom.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -933,7 +933,7 @@ describe('zoom', function() {
expect(chart.scales.y.min).toBe(3);
expect(chart.scales.y.max).toBe(5);
chart.zoom(0.9);
expect(chart.scales.y.min).toBe(2);
expect(chart.scales.y.min).toBe(1);
expect(chart.scales.y.max).toBe(5);
chart.zoom(0.9);
expect(chart.scales.y.min).toBe(1);
Expand Down