From: Toshiki Saito Date: Sun, 27 Nov 2016 03:36:29 +0000 (+0800) Subject: Fixed miscalculation of Bar width. X-Git-Tag: v2.5.0~1^2~34 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=bdcdbc2abf2a57d49dfeb3bd52ee96757cfef555;p=thirdparty%2FChart.js.git Fixed miscalculation of Bar width. for Bar and horizontalBar type, include stacked scale. issue #3589 --- diff --git a/src/controllers/controller.bar.js b/src/controllers/controller.bar.js index e9a85aabd..e5070542e 100644 --- a/src/controllers/controller.bar.js +++ b/src/controllers/controller.bar.js @@ -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) { diff --git a/test/controller.bar.tests.js b/test/controller.bar.tests.js index 15fa00afe..4df23047e 100644 --- a/test/controller.bar.tests.js +++ b/test/controller.bar.tests.js @@ -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, + }] + } + } + }; + }); + }); });