Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/charts/bar.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,10 @@ If this value is a number, it is applied to all sides of the rectangle (left, to

If this value is a number, it is applied to all corners of the rectangle (topLeft, topRight, bottomLeft, bottomRight), except corners touching the [`borderSkipped`](#borderskipped). If this value is an object, the `topLeft` property defines the top-left corners border radius. Similarly, the `topRight`, `bottomLeft`, and `bottomRight` properties can also be specified. Omitted corners and those touching the [`borderSkipped`](#borderskipped) are skipped. For example if the `top` border is skipped, the border radius for the corners `topLeft` and `topRight` will be skipped as well.

:::tip Stacked Charts
When the border radius is supplied as a number and the chart is stacked, the radius will only be applied to the bars that are at the edges of the stack or where the bar is floating. The object syntax can be used to override this behavior.
:::

### Interactions

The interaction with each bar can be controlled with the following properties:
Expand Down
2 changes: 2 additions & 0 deletions src/controllers/controller.bar.js
Original file line number Diff line number Diff line change
Expand Up @@ -269,10 +269,12 @@ export default class BarController extends DatasetController {
const parsed = me.getParsed(i);
const vpixels = reset || isNullOrUndef(parsed[vScale.axis]) ? {base, head: base} : me._calculateBarValuePixels(i);
const ipixels = me._calculateBarIndexPixels(i, ruler);
const stack = (parsed._stacks || {})[vScale.axis];

const properties = {
horizontal,
base: vpixels.base,
enableBorderRadius: !stack || isFloatBar(parsed._custom) || (me.index === stack._top || me.index === stack._bottom),
x: horizontal ? vpixels.head : ipixels.center,
y: horizontal ? ipixels.center : vpixels.head,
height: horizontal ? ipixels.size : undefined,
Expand Down
14 changes: 14 additions & 0 deletions src/core/core.datasetController.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,17 @@ function getOrCreateStack(stacks, stackKey, indexValue) {
return subStack[indexValue] || (subStack[indexValue] = {});
}

function getLastIndexInStack(stack, vScale, positive) {
for (const meta of vScale.getMatchingVisibleMetas('bar').reverse()) {
const value = stack[meta.index];
if ((positive && value > 0) || (!positive && value < 0)) {
return meta.index;
}
}

return null;
}

function updateStacks(controller, parsed) {
const {chart, _cachedMeta: meta} = controller;
const stacks = chart._stacks || (chart._stacks = {}); // map structure is {stackKey: {datasetIndex: value}}
Expand All @@ -143,6 +154,9 @@ function updateStacks(controller, parsed) {
const itemStacks = item._stacks || (item._stacks = {});
stack = itemStacks[vAxis] = getOrCreateStack(stacks, key, index);
stack[datasetIndex] = value;

stack._top = getLastIndexInStack(stack, vScale, true);
stack._bottom = getLastIndexInStack(stack, vScale, false);
}
}

Expand Down
15 changes: 11 additions & 4 deletions src/elements/element.bar.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Element from '../core/core.element';
import {isObject} from '../helpers';
import {addRoundedRectPath} from '../helpers/helpers.canvas';
import {toTRBL, toTRBLCorners} from '../helpers/helpers.options';

Expand Down Expand Up @@ -83,16 +84,21 @@ function parseBorderWidth(bar, maxW, maxH) {
}

function parseBorderRadius(bar, maxW, maxH) {
const {enableBorderRadius} = bar.getProps(['enableBorderRadius']);
const value = bar.options.borderRadius;
const o = toTRBLCorners(value);
const maxR = Math.min(maxW, maxH);
const skip = parseBorderSkipped(bar);

// If the value is an object, assume the user knows what they are doing
// and apply as directed.
const enableBorder = enableBorderRadius || isObject(value);

return {
topLeft: skipOrLimit(skip.top || skip.left, o.topLeft, 0, maxR),
topRight: skipOrLimit(skip.top || skip.right, o.topRight, 0, maxR),
bottomLeft: skipOrLimit(skip.bottom || skip.left, o.bottomLeft, 0, maxR),
bottomRight: skipOrLimit(skip.bottom || skip.right, o.bottomRight, 0, maxR)
topLeft: skipOrLimit(!enableBorder || skip.top || skip.left, o.topLeft, 0, maxR),
topRight: skipOrLimit(!enableBorder || skip.top || skip.right, o.topRight, 0, maxR),
bottomLeft: skipOrLimit(!enableBorder || skip.bottom || skip.left, o.bottomLeft, 0, maxR),
bottomRight: skipOrLimit(!enableBorder || skip.bottom || skip.right, o.bottomRight, 0, maxR)
};
}

Expand Down Expand Up @@ -224,6 +230,7 @@ BarElement.defaults = {
borderSkipped: 'start',
borderWidth: 0,
borderRadius: 0,
enableBorderRadius: true,
pointStyle: undefined
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
module.exports = {
threshold: 0.01,
config: {
type: 'bar',
data: {
labels: [0, 1, 2, 3, 4, 5],
datasets: [
{
backgroundColor: 'red',
data: [12, 19, 12, 5, 4, 12],
},
{
backgroundColor: 'green',
data: [12, 19, -4, 5, 8, 3],
type: 'line'
},
{
backgroundColor: 'blue',
data: [7, 11, -12, 12, 0, -7],
}
]
},
options: {
elements: {
bar: {
borderRadius: Number.MAX_VALUE,
borderWidth: 2,
}
},
scales: {
x: {display: false, stacked: true},
y: {display: false, stacked: true}
}
}
},
options: {
canvas: {
height: 256,
width: 512
}
}
};
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
module.exports = {
threshold: 0.01,
config: {
type: 'bar',
data: {
labels: [0, 1, 2, 3, 4, 5],
datasets: [
{
backgroundColor: 'red',
data: [12, 19, 12, 5, 4, 12],
order: 2,
},
{
backgroundColor: 'green',
data: [12, 19, -4, 5, 8, 3],
order: 1,
},
{
backgroundColor: 'blue',
data: [7, 11, -12, 12, 0, -7],
order: 0,
}
]
},
options: {
elements: {
bar: {
borderRadius: Number.MAX_VALUE,
borderWidth: 2,
}
},
scales: {
x: {display: false, stacked: true},
y: {display: false, stacked: true}
}
}
},
options: {
canvas: {
height: 256,
width: 512
}
}
};
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
module.exports = {
threshold: 0.01,
config: {
type: 'bar',
data: {
labels: [0, 1, 2, 3, 4, 5],
datasets: [
{
backgroundColor: 'red',
data: [12, 19, 12, 5, 4, 12],
},
{
backgroundColor: 'green',
data: [12, 19, -4, 5, 8, 3],
},
{
backgroundColor: 'blue',
data: [7, 11, -12, 12, 0, -7],
}
]
},
options: {
elements: {
bar: {
borderRadius: Number.MAX_VALUE,
borderWidth: 2,
}
},
scales: {
x: {display: false, stacked: true},
y: {display: false, stacked: true}
}
}
},
options: {
canvas: {
height: 256,
width: 512
}
}
};
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
34 changes: 17 additions & 17 deletions test/specs/core.datasetController.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -540,12 +540,12 @@ describe('Chart.DatasetController', function() {

expect(chart._stacks).toEqual({
'x.y.1': {
0: {0: 1, 2: 3},
1: {0: 10, 2: 30}
0: {0: 1, 2: 3, _top: 2, _bottom: null},
1: {0: 10, 2: 30, _top: 2, _bottom: null}
},
'x.y.2': {
0: {1: 2},
1: {1: 20}
0: {1: 2, _top: 1, _bottom: null},
1: {1: 20, _top: 1, _bottom: null}
}
});

Expand All @@ -554,12 +554,12 @@ describe('Chart.DatasetController', function() {

expect(chart._stacks).toEqual({
'x.y.1': {
0: {0: 1},
1: {0: 10}
0: {0: 1, _top: 2, _bottom: null},
1: {0: 10, _top: 2, _bottom: null}
},
'x.y.2': {
0: {1: 2, 2: 3},
1: {1: 20, 2: 30}
0: {1: 2, 2: 3, _top: 2, _bottom: null},
1: {1: 20, 2: 30, _top: 2, _bottom: null}
}
});
});
Expand All @@ -584,12 +584,12 @@ describe('Chart.DatasetController', function() {

expect(chart._stacks).toEqual({
'x.y.1': {
0: {0: 1, 2: 3},
1: {0: 10, 2: 30}
0: {0: 1, 2: 3, _top: 2, _bottom: null},
1: {0: 10, 2: 30, _top: 2, _bottom: null}
},
'x.y.2': {
0: {1: 2},
1: {1: 20}
0: {1: 2, _top: 1, _bottom: null},
1: {1: 20, _top: 1, _bottom: null}
}
});

Expand All @@ -598,12 +598,12 @@ describe('Chart.DatasetController', function() {

expect(chart._stacks).toEqual({
'x.y.1': {
0: {0: 1, 2: 4},
1: {0: 10}
0: {0: 1, 2: 4, _top: 2, _bottom: null},
1: {0: 10, _top: 2, _bottom: null}
},
'x.y.2': {
0: {1: 2},
1: {1: 20}
0: {1: 2, _top: 1, _bottom: null},
1: {1: 20, _top: 1, _bottom: null}
}
});
});
Expand Down Expand Up @@ -719,7 +719,7 @@ describe('Chart.DatasetController', function() {
});

var meta = chart.getDatasetMeta(0);
expect(meta._parsed[0]._stacks).toEqual(jasmine.objectContaining({y: {0: 10, 1: 20}}));
expect(meta._parsed[0]._stacks).toEqual(jasmine.objectContaining({y: {0: 10, 1: 20, _top: null, _bottom: null}}));
});

describe('resolveDataElementOptions', function() {
Expand Down