]> git.ipfire.org Git - thirdparty/Chart.js.git/commitdiff
Fixed miscalculation of Bar width.
authorToshiki Saito <saito@koyo-se.net>
Sun, 27 Nov 2016 03:36:29 +0000 (11:36 +0800)
committerEvert Timberg <evert.timberg+github@gmail.com>
Fri, 2 Dec 2016 12:57:59 +0000 (07:57 -0500)
for Bar and horizontalBar type,
include stacked scale.
issue #3589

src/controllers/controller.bar.js
test/controller.bar.tests.js

index e9a85aabd22a8c925e06949e9b0d092f6b051cef..e5070542e8867354b0c77f635f1683ec047636e3 100644 (file)
@@ -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) {
index 15fa00afed9311e7ec108bacd3358e0bfcb4201b..4df23047e01493908f4afef07d26dc3e571036a9 100644 (file)
@@ -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,
+                                               }]
+                                       }
+                               }
+                       };
+               });
+       });
 });