mirror of
https://github.com/chartjs/Chart.js.git
synced 2025-12-08 20:36:08 +00:00
Fixed miscalculation of Bar width.
for Bar and horizontalBar type, include stacked scale. issue #3589
This commit is contained in:
parent
b39c0e1f93
commit
bdcdbc2abf
@ -74,7 +74,7 @@ module.exports = function(Chart) {
|
||||
rectangle._datasetIndex = me.index;
|
||||
rectangle._index = index;
|
||||
|
||||
var ruler = me.getRuler(index);
|
||||
var ruler = me.getRuler(index); // The index argument for compatible
|
||||
rectangle._model = {
|
||||
x: me.calculateBarX(index, me.index, ruler),
|
||||
y: reset ? scaleBase : me.calculateBarY(index, me.index),
|
||||
@ -121,29 +121,17 @@ module.exports = function(Chart) {
|
||||
return yScale.getBasePixel();
|
||||
},
|
||||
|
||||
getRuler: function(index) {
|
||||
getRuler: function() {
|
||||
var me = this;
|
||||
var meta = me.getMeta();
|
||||
var xScale = me.getScaleForId(meta.xAxisID);
|
||||
var datasetCount = me.getBarCount();
|
||||
|
||||
var tickWidth;
|
||||
|
||||
if (xScale.options.type === 'category') {
|
||||
tickWidth = xScale.getPixelForTick(index + 1) - xScale.getPixelForTick(index);
|
||||
} else {
|
||||
// Average width
|
||||
tickWidth = xScale.width / xScale.ticks.length;
|
||||
}
|
||||
var tickWidth = xScale.width / xScale.ticks.length;
|
||||
var categoryWidth = tickWidth * xScale.options.categoryPercentage;
|
||||
var categorySpacing = (tickWidth - (tickWidth * xScale.options.categoryPercentage)) / 2;
|
||||
var fullBarWidth = categoryWidth / datasetCount;
|
||||
|
||||
if (xScale.ticks.length !== me.chart.data.labels.length) {
|
||||
var perc = xScale.ticks.length / me.chart.data.labels.length;
|
||||
fullBarWidth = fullBarWidth * perc;
|
||||
}
|
||||
|
||||
var barWidth = fullBarWidth * xScale.options.barPercentage;
|
||||
var barSpacing = fullBarWidth - (fullBarWidth * xScale.options.barPercentage);
|
||||
|
||||
@ -163,7 +151,7 @@ module.exports = function(Chart) {
|
||||
if (xScale.options.barThickness) {
|
||||
return xScale.options.barThickness;
|
||||
}
|
||||
return xScale.options.stacked ? ruler.categoryWidth : ruler.barWidth;
|
||||
return xScale.options.stacked ? ruler.categoryWidth * xScale.options.barPercentage : ruler.barWidth;
|
||||
},
|
||||
|
||||
// Get bar index from the given dataset index accounting for the fact that not all bars are visible
|
||||
@ -346,7 +334,7 @@ module.exports = function(Chart) {
|
||||
rectangle._datasetIndex = me.index;
|
||||
rectangle._index = index;
|
||||
|
||||
var ruler = me.getRuler(index);
|
||||
var ruler = me.getRuler(index); // The index argument for compatible
|
||||
rectangle._model = {
|
||||
x: reset ? scaleBase : me.calculateBarX(index, me.index),
|
||||
y: me.calculateBarY(index, me.index, ruler),
|
||||
@ -449,28 +437,17 @@ module.exports = function(Chart) {
|
||||
return xScale.getBasePixel();
|
||||
},
|
||||
|
||||
getRuler: function(index) {
|
||||
getRuler: function() {
|
||||
var me = this;
|
||||
var meta = me.getMeta();
|
||||
var yScale = me.getScaleForId(meta.yAxisID);
|
||||
var datasetCount = me.getBarCount();
|
||||
|
||||
var tickHeight;
|
||||
if (yScale.options.type === 'category') {
|
||||
tickHeight = yScale.getPixelForTick(index + 1) - yScale.getPixelForTick(index);
|
||||
} else {
|
||||
// Average width
|
||||
tickHeight = yScale.width / yScale.ticks.length;
|
||||
}
|
||||
var tickHeight = yScale.height / yScale.ticks.length;
|
||||
var categoryHeight = tickHeight * yScale.options.categoryPercentage;
|
||||
var categorySpacing = (tickHeight - (tickHeight * yScale.options.categoryPercentage)) / 2;
|
||||
var fullBarHeight = categoryHeight / datasetCount;
|
||||
|
||||
if (yScale.ticks.length !== me.chart.data.labels.length) {
|
||||
var perc = yScale.ticks.length / me.chart.data.labels.length;
|
||||
fullBarHeight = fullBarHeight * perc;
|
||||
}
|
||||
|
||||
var barHeight = fullBarHeight * yScale.options.barPercentage;
|
||||
var barSpacing = fullBarHeight - (fullBarHeight * yScale.options.barPercentage);
|
||||
|
||||
@ -491,7 +468,7 @@ module.exports = function(Chart) {
|
||||
if (yScale.options.barThickness) {
|
||||
return yScale.options.barThickness;
|
||||
}
|
||||
return yScale.options.stacked ? ruler.categoryHeight : ruler.barHeight;
|
||||
return yScale.options.stacked ? ruler.categoryHeight * yScale.options.barPercentage : ruler.barHeight;
|
||||
},
|
||||
|
||||
calculateBarX: function(index, datasetIndex) {
|
||||
|
||||
@ -240,7 +240,8 @@ describe('Bar controller tests', function() {
|
||||
scales: {
|
||||
xAxes: [{
|
||||
type: 'category',
|
||||
stacked: true
|
||||
stacked: true,
|
||||
barPercentage: 1
|
||||
}],
|
||||
yAxes: [{
|
||||
type: 'linear',
|
||||
@ -296,7 +297,8 @@ describe('Bar controller tests', function() {
|
||||
scales: {
|
||||
xAxes: [{
|
||||
type: 'category',
|
||||
stacked: true
|
||||
stacked: true,
|
||||
barPercentage: 1
|
||||
}],
|
||||
yAxes: [{
|
||||
type: 'linear',
|
||||
@ -487,4 +489,154 @@ describe('Bar controller tests', function() {
|
||||
expect(bar._model.borderColor).toBe('rgb(0, 255, 0)');
|
||||
expect(bar._model.borderWidth).toBe(1.5);
|
||||
});
|
||||
|
||||
describe('Bar width', function() {
|
||||
beforeEach(function() {
|
||||
// 2 datasets
|
||||
this.data = {
|
||||
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
|
||||
datasets: [{
|
||||
data: [10, 20, 30, 40, 50, 60, 70],
|
||||
}, {
|
||||
data: [10, 20, 30, 40, 50, 60, 70],
|
||||
}]
|
||||
};
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
var chart = window.acquireChart(this.config);
|
||||
var meta = chart.getDatasetMeta(0);
|
||||
var xScale = chart.scales[meta.xAxisID];
|
||||
|
||||
var categoryPercentage = xScale.options.categoryPercentage;
|
||||
var barPercentage = xScale.options.barPercentage;
|
||||
var stacked = xScale.options.stacked;
|
||||
|
||||
var totalBarWidth = 0;
|
||||
for (var i = 0; i < chart.data.datasets.length; i++) {
|
||||
var bars = chart.getDatasetMeta(i).data;
|
||||
for (var j = xScale.minIndex; j <= xScale.maxIndex; j++) {
|
||||
totalBarWidth += bars[j]._model.width;
|
||||
}
|
||||
if (stacked) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var actualValue = totalBarWidth;
|
||||
var expectedValue = xScale.width * categoryPercentage * barPercentage;
|
||||
expect(actualValue).toBeCloseToPixel(expectedValue);
|
||||
|
||||
});
|
||||
|
||||
it('should correctly set bar width when min and max option is set.', function() {
|
||||
this.config = {
|
||||
type: 'bar',
|
||||
data: this.data,
|
||||
options: {
|
||||
scales: {
|
||||
xAxes: [{
|
||||
ticks: {
|
||||
min: 'March',
|
||||
max: 'May',
|
||||
},
|
||||
}]
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
it('should correctly set bar width when scale are stacked with min and max options.', function() {
|
||||
this.config = {
|
||||
type: 'bar',
|
||||
data: this.data,
|
||||
options: {
|
||||
scales: {
|
||||
xAxes: [{
|
||||
ticks: {
|
||||
min: 'March',
|
||||
max: 'May',
|
||||
},
|
||||
stacked: true,
|
||||
}]
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
describe('Bar height (horizontalBar type)', function() {
|
||||
beforeEach(function() {
|
||||
// 2 datasets
|
||||
this.data = {
|
||||
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
|
||||
datasets: [{
|
||||
data: [10, 20, 30, 40, 50, 60, 70],
|
||||
}, {
|
||||
data: [10, 20, 30, 40, 50, 60, 70],
|
||||
}]
|
||||
};
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
var chart = window.acquireChart(this.config);
|
||||
var meta = chart.getDatasetMeta(0);
|
||||
var yScale = chart.scales[meta.yAxisID];
|
||||
|
||||
var categoryPercentage = yScale.options.categoryPercentage;
|
||||
var barPercentage = yScale.options.barPercentage;
|
||||
var stacked = yScale.options.stacked;
|
||||
|
||||
var totalBarHeight = 0;
|
||||
for (var i = 0; i < chart.data.datasets.length; i++) {
|
||||
var bars = chart.getDatasetMeta(i).data;
|
||||
for (var j = yScale.minIndex; j <= yScale.maxIndex; j++) {
|
||||
totalBarHeight += bars[j]._model.height;
|
||||
}
|
||||
if (stacked) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var actualValue = totalBarHeight;
|
||||
var expectedValue = yScale.height * categoryPercentage * barPercentage;
|
||||
expect(actualValue).toBeCloseToPixel(expectedValue);
|
||||
|
||||
});
|
||||
|
||||
it('should correctly set bar height when min and max option is set.', function() {
|
||||
this.config = {
|
||||
type: 'horizontalBar',
|
||||
data: this.data,
|
||||
options: {
|
||||
scales: {
|
||||
yAxes: [{
|
||||
ticks: {
|
||||
min: 'March',
|
||||
max: 'May',
|
||||
},
|
||||
}]
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
it('should correctly set bar height when scale are stacked with min and max options.', function() {
|
||||
this.config = {
|
||||
type: 'horizontalBar',
|
||||
data: this.data,
|
||||
options: {
|
||||
scales: {
|
||||
yAxes: [{
|
||||
ticks: {
|
||||
min: 'March',
|
||||
max: 'May',
|
||||
},
|
||||
stacked: true,
|
||||
}]
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user