Skip to content

Commit f93dd0b

Browse files
Chart: fix axes synchronization when chats not overlap (#30217)
1 parent ff29650 commit f93dd0b

File tree

3 files changed

+122
-48
lines changed

3 files changed

+122
-48
lines changed

packages/devextreme/js/viz/axes/base_axis.js

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1872,17 +1872,35 @@ Axis.prototype = {
18721872
};
18731873
},
18741874

1875+
_shouldCorrectValuesToZero(minValue, maxValue) {
1876+
if(this.isArgumentAxis || this._options.dataType === 'datetime') {
1877+
return false;
1878+
}
1879+
1880+
const dataRange = this._getViewportRange();
1881+
1882+
if(minValue > dataRange.max || minValue > dataRange.maxVisible) {
1883+
return false;
1884+
}
1885+
1886+
if(maxValue < dataRange.min || maxValue < dataRange.minVisible) {
1887+
return false;
1888+
}
1889+
1890+
return true;
1891+
},
18751892
getCorrectedValuesToZero(minValue, maxValue) {
18761893
const that = this;
18771894
const translator = that._translator;
18781895
const canvasStartEnd = that._getCanvasStartEnd();
18791896
const dataRange = that._getViewportRange();
18801897
const screenDelta = that._getScreenDelta();
1881-
const options = that._options;
1898+
18821899
let start;
18831900
let end;
18841901
let correctedMin;
18851902
let correctedMax;
1903+
18861904
const correctZeroLevel = (minPoint, maxPoint) => {
18871905
const minExpectedPadding = _abs(canvasStartEnd.start - minPoint);
18881906
const maxExpectedPadding = _abs(canvasStartEnd.end - maxPoint);
@@ -1892,7 +1910,8 @@ Axis.prototype = {
18921910
start = minExpectedPadding / coeff;
18931911
end = maxExpectedPadding / coeff;
18941912
};
1895-
if(!that.isArgumentAxis && options.dataType !== 'datetime') {
1913+
1914+
if(that._shouldCorrectValuesToZero(minValue, maxValue)) {
18961915
if(minValue * dataRange.min <= 0 && minValue * dataRange.minVisible <= 0) {
18971916
correctZeroLevel(translator.translate(0), translator.translate(maxValue));
18981917
correctedMin = 0;
@@ -1903,6 +1922,7 @@ Axis.prototype = {
19031922
correctedMax = 0;
19041923
}
19051924
}
1925+
19061926
return {
19071927
start: isFinite(start) ? start : null,
19081928
end: isFinite(end) ? end : null,

packages/devextreme/js/viz/chart_components/multi_axes_synchronizer.js

Lines changed: 46 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -192,30 +192,33 @@ function getMainAxisInfo(axesInfo) {
192192

193193
function correctMinMaxValues(axesInfo) {
194194
const mainAxisInfo = getMainAxisInfo(axesInfo);
195-
const mainAxisInfoTickInterval = mainAxisInfo.tickInterval;
195+
const mainAxisRange = getAxisRange(mainAxisInfo);
196196

197197
axesInfo.forEach(axisInfo => {
198-
let scale;
199-
let move;
200-
let mainAxisBaseValueOffset;
201-
let valueFromAxisInfo;
202-
203198
if(axisInfo !== mainAxisInfo) {
204-
if(mainAxisInfoTickInterval && axisInfo.tickInterval) {
199+
if(mainAxisInfo.tickInterval && axisInfo.tickInterval) {
200+
const tickIntervalScale = axisInfo.tickInterval / mainAxisInfo.tickInterval;
201+
205202
if(axisInfo.stubData && isDefined(axisInfo.synchronizedValue)) {
206-
axisInfo.oldMinValue = axisInfo.minValue = axisInfo.baseTickValue - (mainAxisInfo.baseTickValue - mainAxisInfo.minValue) / mainAxisInfoTickInterval * axisInfo.tickInterval;
207-
axisInfo.oldMaxValue = axisInfo.maxValue = axisInfo.baseTickValue - (mainAxisInfo.baseTickValue - mainAxisInfo.maxValue) / mainAxisInfoTickInterval * axisInfo.tickInterval;
203+
axisInfo.oldMinValue = axisInfo.minValue = axisInfo.baseTickValue - (mainAxisInfo.baseTickValue - mainAxisInfo.minValue) * tickIntervalScale;
204+
axisInfo.oldMaxValue = axisInfo.maxValue = axisInfo.baseTickValue - (mainAxisInfo.baseTickValue - mainAxisInfo.maxValue) * tickIntervalScale;
208205
}
209-
scale = mainAxisInfoTickInterval / getAxisRange(mainAxisInfo) / axisInfo.tickInterval * getAxisRange(axisInfo);
210-
axisInfo.maxValue = axisInfo.minValue + getAxisRange(axisInfo) / scale;
206+
207+
axisInfo.maxValue = axisInfo.minValue + tickIntervalScale * mainAxisRange;
211208
}
212-
if((mainAxisInfo.inverted && !axisInfo.inverted) || (!mainAxisInfo.inverted && axisInfo.inverted)) {
209+
210+
let mainAxisBaseValueOffset;
211+
212+
if(!!mainAxisInfo.inverted !== !!axisInfo.inverted) {
213213
mainAxisBaseValueOffset = mainAxisInfo.maxValue - mainAxisInfo.invertedBaseTickValue;
214214
} else {
215215
mainAxisBaseValueOffset = mainAxisInfo.baseTickValue - mainAxisInfo.minValue;
216216
}
217-
valueFromAxisInfo = getAxisRange(axisInfo);
218-
move = (mainAxisBaseValueOffset / getAxisRange(mainAxisInfo) - (axisInfo.baseTickValue - axisInfo.minValue) / valueFromAxisInfo) * valueFromAxisInfo;
217+
218+
const axisBaseValueOffset = axisInfo.baseTickValue - axisInfo.minValue;
219+
const scaledMainAxisBaseValueOffset = mainAxisBaseValueOffset * getAxisRange(axisInfo) / mainAxisRange;
220+
const move = scaledMainAxisBaseValueOffset - axisBaseValueOffset;
221+
219222
axisInfo.minValue -= move;
220223
axisInfo.maxValue -= move;
221224
}
@@ -365,18 +368,8 @@ function updateMinorTicks(axesInfo) {
365368
}
366369

367370
function allAxesValuesOnSameSideFromZero(axesInfo) {
368-
let allPositive = true;
369-
let allNegative = true;
370-
371-
axesInfo.forEach((axis) => {
372-
if(axis.oldMinValue > 0 || axis.oldMaxValue > 0) {
373-
allNegative = false;
374-
}
375-
376-
if(axis.oldMinValue < 0 || axis.oldMaxValue < 0) {
377-
allPositive = false;
378-
}
379-
});
371+
const allPositive = axesInfo.every(({ oldMinValue, oldMaxValue }) => oldMinValue >= 0 && oldMaxValue >= 0);
372+
const allNegative = axesInfo.every(({ oldMinValue, oldMaxValue }) => oldMinValue <= 0 && oldMaxValue <= 0);
380373

381374
return allPositive || allNegative;
382375
}
@@ -387,8 +380,9 @@ function correctPaddings(axesInfo, paddings) {
387380
}
388381

389382
return axesInfo.reduce((prev, info) => {
390-
const inverted = info.inverted;
391-
const { start, end } = info.axis.getCorrectedValuesToZero(info.minValue, info.maxValue);
383+
const { inverted, minValue, maxValue } = info;
384+
const { start, end } = info.axis.getCorrectedValuesToZero(minValue, maxValue);
385+
392386
if(isDefined(start) || isDefined(end)) {
393387
return inverted ? {
394388
start: prev.start,
@@ -398,38 +392,44 @@ function correctPaddings(axesInfo, paddings) {
398392
end: prev.end
399393
};
400394
}
395+
401396
return prev;
402397
}, paddings);
403398
}
404399

405400
const multiAxesSynchronizer = {
406401
synchronize: function(valueAxes) {
407402
each(getValueAxesPerPanes(valueAxes), function(_, axes) {
408-
let axesInfo;
409-
let paddings;
410-
if(axes.length > 1) {
411-
axesInfo = populateAxesInfo(axes);
412-
if(axesInfo.length < 2 || !getMainAxisInfo(axesInfo)) return;
413-
updateTickValues(axesInfo);
403+
if(axes.length <= 1) {
404+
return;
405+
}
414406

415-
correctMinMaxValues(axesInfo);
407+
const axesInfo = populateAxesInfo(axes);
416408

417-
paddings = calculatePaddings(axesInfo);
418-
paddings = correctPaddings(axesInfo, paddings);
409+
if(axesInfo.length < 2 || !getMainAxisInfo(axesInfo)) {
410+
return;
411+
}
419412

420-
correctMinMaxValuesByPaddings(axesInfo, paddings);
413+
updateTickValues(axesInfo);
421414

422-
correctAfterSynchronize(axesInfo);
415+
correctMinMaxValues(axesInfo);
423416

424-
updateTickValuesIfSynchronizedValueUsed(axesInfo);
417+
let paddings = calculatePaddings(axesInfo);
418+
paddings = correctPaddings(axesInfo, paddings);
425419

426-
updateMinorTicks(axesInfo);
420+
correctMinMaxValuesByPaddings(axesInfo, paddings);
427421

428-
axesInfo.forEach(info => {
429-
convertAxisInfo(info, logConverter(info.axis.getTranslator().getBusinessRange()));
430-
});
431-
applyMinMaxValues(axesInfo);
432-
}
422+
correctAfterSynchronize(axesInfo);
423+
424+
updateTickValuesIfSynchronizedValueUsed(axesInfo);
425+
426+
updateMinorTicks(axesInfo);
427+
428+
axesInfo.forEach(info => {
429+
convertAxisInfo(info, logConverter(info.axis.getTranslator().getBusinessRange()));
430+
});
431+
432+
applyMinMaxValues(axesInfo);
433433
});
434434
}
435435
};

packages/devextreme/testing/tests/DevExpress.viz.charts/multiAxesSynchronizer.tests.js

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1839,6 +1839,60 @@ QUnit.test('Synchronization two axis with paddins, inverted axis, non zero paddi
18391839
});
18401840
});
18411841

1842+
QUnit.test('Synchronization two axis with synchronizedValue and not overlapped values for 2 axis, not correct zero value (T1295525)', function(assert) {
1843+
checkAxesSynchronization(assert, {
1844+
axesOptions: [
1845+
{
1846+
range: {
1847+
axisType: 'continuous',
1848+
max: 425000,
1849+
maxVisible: 425000,
1850+
min: 0,
1851+
minVisible: 280000
1852+
},
1853+
tickValues: [250000, 300000, 325000, 350000, 375000, 400000, 425000],
1854+
tickInterval: 25000,
1855+
synchronizedValue: 0,
1856+
},
1857+
{
1858+
range: {
1859+
axisType: 'continuous',
1860+
max: 28,
1861+
maxVisible: 28,
1862+
min: 0,
1863+
minVisible: 0
1864+
},
1865+
tickValues: [0, 5, 10, 15, 20, 25, 30],
1866+
tickInterval: 5,
1867+
synchronizedValue: 0,
1868+
}
1869+
],
1870+
axesOptionsAfterSync: [
1871+
{
1872+
range: {
1873+
axisType: 'continuous',
1874+
min: 0,
1875+
minVisible: 0,
1876+
max: 425000,
1877+
maxVisible: 425000
1878+
},
1879+
tickValues: [0, 25000, 50000, 75000, 100000, 125000, 150000, 175000, 200000, 225000, 250000, 275000, 300000, 325000, 350000, 375000, 400000, 425000]
1880+
},
1881+
{
1882+
range: {
1883+
axisType: 'continuous',
1884+
min: 0,
1885+
minVisible: 0,
1886+
max: 85,
1887+
maxVisible: 85,
1888+
},
1889+
tickValues: [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85]
1890+
}
1891+
],
1892+
syncIndexes: [[0, 0]]
1893+
});
1894+
});
1895+
18421896
QUnit.test('Synchronization two continuous axis. B250542', function(assert) {
18431897
const tickValues1 = [-2, -1, 0, 1, 2, 3];
18441898
const tickValue2 = [10, 20, 30, 40, 50, 60, 70, 80, 90];

0 commit comments

Comments
 (0)