Skip to content

Commit

Permalink
Fix bar draw issue with borderWidth. (#3680)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
KoyoSE authored and etimberg committed Dec 20, 2016
1 parent 64b5def commit 5387c48
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 75 deletions.
58 changes: 2 additions & 56 deletions src/controllers/controller.bar.js
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -348,69 +349,14 @@ 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),
borderSkipped: custom.borderSkipped ? custom.borderSkipped : rectangleElementOptions.borderSkipped,
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();
},
Expand Down
66 changes: 49 additions & 17 deletions src/elements/element.rectangle.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -104,7 +136,7 @@ module.exports = function(Chart) {
}

ctx.fill();
if (vm.borderWidth) {
if (borderWidth) {
ctx.stroke();
}
},
Expand Down
4 changes: 2 additions & 2 deletions test/element.rectangle.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down

0 comments on commit 5387c48

Please sign in to comment.