Merge pull request #2128 from The-Smallest/v2-rectangle-generic

Generic Rectangle: any border (botton, left, top, right) can be skipped now.
This commit is contained in:
Evert Timberg 2016-03-13 14:06:31 -04:00
commit e511fc2a1c
6 changed files with 91 additions and 8 deletions

View File

@ -236,6 +236,7 @@ rectangle | - | - | -
*rectangle*.backgroundColor | Color | `Chart.defaults.global.defaultColor` | Default bar fill color
*rectangle*.borderWidth | Number | 0 | Default bar stroke width
*rectangle*.borderColor | Color | `Chart.defaults.global.defaultColor` | Default bar stroke color
*rectangle*.borderSkipped | String | 'bottom' | Default skipped (excluded) border for rectangle. Can be one of `bottom`, `left`, `top`, `right`
If for example, you wanted all charts created to be responsive, and resize when the browser window does, the following setting can be changed:

View File

@ -66,7 +66,8 @@
elements: {
rectangle: {
borderWidth: 2,
borderColor: 'rgb(0, 255, 0)'
borderColor: 'rgb(0, 255, 0)',
borderSkipped: 'bottom'
}
},
responsive: true,

View File

@ -116,6 +116,7 @@ module.exports = function(Chart) {
base: reset ? yScalePoint : this.calculateBarBase(this.index, index),
width: this.calculateBarWidth(numBars),
backgroundColor: rectangle.custom && rectangle.custom.backgroundColor ? rectangle.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.getDataset().backgroundColor, index, this.chart.options.elements.rectangle.backgroundColor),
borderSkipped: rectangle.custom && rectangle.custom.borderSkipped ? rectangle.custom.borderSkipped : this.chart.options.elements.rectangle.borderSkipped,
borderColor: rectangle.custom && rectangle.custom.borderColor ? rectangle.custom.borderColor : helpers.getValueAtIndexOrDefault(this.getDataset().borderColor, index, this.chart.options.elements.rectangle.borderColor),
borderWidth: rectangle.custom && rectangle.custom.borderWidth ? rectangle.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.getDataset().borderWidth, index, this.chart.options.elements.rectangle.borderWidth)
}

View File

@ -7,7 +7,8 @@ module.exports = function(Chart) {
Chart.defaults.global.elements.rectangle = {
backgroundColor: Chart.defaults.global.defaultColor,
borderWidth: 0,
borderColor: Chart.defaults.global.defaultColor
borderColor: Chart.defaults.global.defaultColor,
borderSkipped: 'bottom'
};
Chart.elements.Rectangle = Chart.Element.extend({
@ -36,12 +37,31 @@ module.exports = function(Chart) {
ctx.strokeStyle = vm.borderColor;
ctx.lineWidth = vm.borderWidth;
// It'd be nice to keep this class totally generic to any rectangle
// and simply specify which border to miss out.
ctx.moveTo(leftX, vm.base);
ctx.lineTo(leftX, top);
ctx.lineTo(rightX, top);
ctx.lineTo(rightX, vm.base);
// 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]
];
// 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(index) {
return corners[(startCorner + index) % 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();

View File

@ -204,6 +204,7 @@ describe('Bar controller tests', function() {
elements: {
rectangle: {
backgroundColor: 'rgb(255, 0, 0)',
borderSkipped: 'top',
borderColor: 'rgb(0, 0, 255)',
borderWidth: 2,
}
@ -247,6 +248,7 @@ describe('Bar controller tests', function() {
base: 194,
width: 13.680000000000001,
backgroundColor: 'rgb(255, 0, 0)',
borderSkipped: 'top',
borderColor: 'rgb(0, 0, 255)',
borderWidth: 2,
});
@ -264,6 +266,7 @@ describe('Bar controller tests', function() {
base: 194,
width: 13.680000000000001,
backgroundColor: 'rgb(255, 0, 0)',
borderSkipped: 'top',
borderColor: 'rgb(0, 0, 255)',
borderWidth: 2,
});

View File

@ -242,5 +242,62 @@ describe('Rectangle element tests', function() {
}]);
});
function testBorderSkipped (borderSkipped, expectedDrawCalls) {
var mockContext = window.createMockContext();
var rectangle = new Chart.elements.Rectangle({
_chart: { ctx: mockContext }
});
// Attach a view object as if we were the controller
rectangle._view = {
borderSkipped: borderSkipped, // set tested 'borderSkipped' parameter
ctx: mockContext,
base: 0,
width: 4,
x: 10,
y: 15,
};
rectangle.draw();
var drawCalls = rectangle._view.ctx.getCalls().splice(4, 4);
expect(drawCalls).toEqual(expectedDrawCalls);
}
it ('should draw correctly respecting "borderSkipped" == "bottom"', function() {
testBorderSkipped ('bottom', [
{ name: 'moveTo', args: [8, 0] },
{ name: 'lineTo', args: [8, 15] },
{ name: 'lineTo', args: [12, 15] },
{ name: 'lineTo', args: [12, 0] },
]);
});
it ('should draw correctly respecting "borderSkipped" == "left"', function() {
testBorderSkipped ('left', [
{ name: 'moveTo', args: [8, 15] },
{ name: 'lineTo', args: [12, 15] },
{ name: 'lineTo', args: [12, 0] },
{ name: 'lineTo', args: [8, 0] },
]);
});
it ('should draw correctly respecting "borderSkipped" == "top"', function() {
testBorderSkipped ('top', [
{ name: 'moveTo', args: [12, 15] },
{ name: 'lineTo', args: [12, 0] },
{ name: 'lineTo', args: [8, 0] },
{ name: 'lineTo', args: [8, 15] },
]);
});
it ('should draw correctly respecting "borderSkipped" == "right"', function() {
testBorderSkipped ('right', [
{ name: 'moveTo', args: [12, 0] },
{ name: 'lineTo', args: [8, 0] },
{ name: 'lineTo', args: [8, 15] },
{ name: 'lineTo', args: [12, 15] },
]);
});
});