]> git.ipfire.org Git - thirdparty/Chart.js.git/commitdiff
Fix bar draw issue with `borderWidth`. (#3680)
authorSAiTO TOSHiKi <saito@koyo-se.net>
Tue, 20 Dec 2016 14:01:07 +0000 (22:01 +0800)
committerEvert Timberg <evert.timberg+github@gmail.com>
Tue, 20 Dec 2016 14:01:07 +0000 (09:01 -0500)
Fix bar draw issue.
1. `Chart.elements.Rectangle.draw` function supports both horizontal and vertical bar.
2. Corrected bar position at minus.
3. Adjust bar size when `borderWidth` is set.
4. Adjust bar size when `borderSkipped` is set.
5. Adjust `borderWidth` with value near 0(base).
6. Update test.

src/controllers/controller.bar.js
src/elements/element.rectangle.js
test/element.rectangle.tests.js

index fc2f1c0c662ff62f5ee822b80e688e591651b557..ecf43b19bce6d91046bc6afb7e68436a115b690a 100644 (file)
@@ -84,6 +84,7 @@ module.exports = function(Chart) {
                                datasetLabel: dataset.label,
 
                                // Appearance
+                               horizontal: false,
                                base: reset ? scaleBase : me.calculateBarBase(me.index, index),
                                width: me.calculateBarWidth(ruler),
                                backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, rectangleElementOptions.backgroundColor),
@@ -348,6 +349,7 @@ module.exports = function(Chart) {
                                datasetLabel: dataset.label,
 
                                // Appearance
+                               horizontal: true,
                                base: reset ? scaleBase : me.calculateBarBase(me.index, index),
                                height: me.calculateBarHeight(ruler),
                                backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, rectangleElementOptions.backgroundColor),
@@ -355,62 +357,6 @@ module.exports = function(Chart) {
                                borderColor: custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, rectangleElementOptions.borderColor),
                                borderWidth: custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, rectangleElementOptions.borderWidth)
                        };
-                       rectangle.draw = function() {
-                               var ctx = this._chart.ctx;
-                               var vm = this._view;
-
-                               var halfHeight = vm.height / 2,
-                                       topY = vm.y - halfHeight,
-                                       bottomY = vm.y + halfHeight,
-                                       right = vm.base - (vm.base - vm.x),
-                                       halfStroke = vm.borderWidth / 2;
-
-                               // Canvas doesn't allow us to stroke inside the width so we can
-                               // adjust the sizes to fit if we're setting a stroke on the line
-                               if (vm.borderWidth) {
-                                       topY += halfStroke;
-                                       bottomY -= halfStroke;
-                                       right += halfStroke;
-                               }
-
-                               ctx.beginPath();
-
-                               ctx.fillStyle = vm.backgroundColor;
-                               ctx.strokeStyle = vm.borderColor;
-                               ctx.lineWidth = vm.borderWidth;
-
-                               // Corner points, from bottom-left to bottom-right clockwise
-                               // | 1 2 |
-                               // | 0 3 |
-                               var corners = [
-                                       [vm.base, bottomY],
-                                       [vm.base, topY],
-                                       [right, topY],
-                                       [right, bottomY]
-                               ];
-
-                               // Find first (starting) corner with fallback to 'bottom'
-                               var borders = ['bottom', 'left', 'top', 'right'];
-                               var startCorner = borders.indexOf(vm.borderSkipped, 0);
-                               if (startCorner === -1) {
-                                       startCorner = 0;
-                               }
-
-                               function cornerAt(cornerIndex) {
-                                       return corners[(startCorner + cornerIndex) % 4];
-                               }
-
-                               // Draw rectangle from 'startCorner'
-                               ctx.moveTo.apply(ctx, cornerAt(0));
-                               for (var i = 1; i < 4; i++) {
-                                       ctx.lineTo.apply(ctx, cornerAt(i));
-                               }
-
-                               ctx.fill();
-                               if (vm.borderWidth) {
-                                       ctx.stroke();
-                               }
-                       };
 
                        rectangle.pivot();
                },
index 427916791eda915f54cc4067c4f923646b929a7e..c3b819761408b52c25f5b3132f1a2a55d3b785f3 100644 (file)
@@ -53,39 +53,71 @@ module.exports = function(Chart) {
                draw: function() {
                        var ctx = this._chart.ctx;
                        var vm = this._view;
-
-                       var halfWidth = vm.width / 2,
-                               leftX = vm.x - halfWidth,
-                               rightX = vm.x + halfWidth,
-                               top = vm.base - (vm.base - vm.y),
-                               halfStroke = vm.borderWidth / 2;
+                       var left, right, top, bottom, signX, signY, borderSkipped;
+                       var borderWidth = vm.borderWidth;
+
+                       if (!vm.horizontal) {
+                               // bar
+                               left = vm.x - vm.width / 2;
+                               right = vm.x + vm.width / 2;
+                               top = vm.y;
+                               bottom = vm.base;
+                               signX = 1;
+                               signY = bottom > top? 1: -1;
+                               borderSkipped = vm.borderSkipped || 'bottom';
+                       } else {
+                               // horizontal bar
+                               left = vm.base;
+                               right = vm.x;
+                               top = vm.y - vm.height / 2;
+                               bottom = vm.y + vm.height / 2;
+                               signX = right > left? 1: -1;
+                               signY = 1;
+                               borderSkipped = vm.borderSkipped || 'left';
+                       }
 
                        // Canvas doesn't allow us to stroke inside the width so we can
                        // adjust the sizes to fit if we're setting a stroke on the line
-                       if (vm.borderWidth) {
-                               leftX += halfStroke;
-                               rightX -= halfStroke;
-                               top += halfStroke;
+                       if (borderWidth) {
+                               // borderWidth shold be less than bar width and bar height.
+                               var barSize = Math.min(Math.abs(left - right), Math.abs(top - bottom));
+                               borderWidth = borderWidth > barSize? barSize: borderWidth;
+                               var halfStroke = borderWidth / 2;
+                               // Adjust borderWidth when bar top position is near vm.base(zero).
+                               var borderLeft = left + (borderSkipped !== 'left'? halfStroke * signX: 0);
+                               var borderRight = right + (borderSkipped !== 'right'? -halfStroke * signX: 0);
+                               var borderTop = top + (borderSkipped !== 'top'? halfStroke * signY: 0);
+                               var borderBottom = bottom + (borderSkipped !== 'bottom'? -halfStroke * signY: 0);
+                               // not become a vertical line?
+                               if (borderLeft !== borderRight) {
+                                       top = borderTop;
+                                       bottom = borderBottom;
+                               }
+                               // not become a horizontal line?
+                               if (borderTop !== borderBottom) {
+                                       left = borderLeft;
+                                       right = borderRight;
+                               }
                        }
 
                        ctx.beginPath();
                        ctx.fillStyle = vm.backgroundColor;
                        ctx.strokeStyle = vm.borderColor;
-                       ctx.lineWidth = vm.borderWidth;
+                       ctx.lineWidth = borderWidth;
 
                        // Corner points, from bottom-left to bottom-right clockwise
                        // | 1 2 |
                        // | 0 3 |
                        var corners = [
-                               [leftX, vm.base],
-                               [leftX, top],
-                               [rightX, top],
-                               [rightX, vm.base]
+                               [left, bottom],
+                               [left, top],
+                               [right, top],
+                               [right, bottom]
                        ];
 
                        // Find first (starting) corner with fallback to 'bottom'
                        var borders = ['bottom', 'left', 'top', 'right'];
-                       var startCorner = borders.indexOf(vm.borderSkipped, 0);
+                       var startCorner = borders.indexOf(borderSkipped, 0);
                        if (startCorner === -1) {
                                startCorner = 0;
                        }
@@ -104,7 +136,7 @@ module.exports = function(Chart) {
                        }
 
                        ctx.fill();
-                       if (vm.borderWidth) {
+                       if (borderWidth) {
                                ctx.stroke();
                        }
                },
index b833862bd6f8d83519f24c89a97ce41a45df05c6..e72117f5a36584b24c02f0311f297c34f023e2b5 100644 (file)
@@ -207,10 +207,10 @@ describe('Rectangle element tests', function() {
                        args: [8.5, 0]
                }, {
                        name: 'lineTo',
-                       args: [8.5, 15.5]
+                       args: [8.5, 14.5] // This is a minus bar. Not 15.5
                }, {
                        name: 'lineTo',
-                       args: [11.5, 15.5]
+                       args: [11.5, 14.5]
                }, {
                        name: 'lineTo',
                        args: [11.5, 0]