Skip to content

Commit

Permalink
Bar: add 'middle' option for borderSkipped (#9452)
Browse files Browse the repository at this point in the history
* Bar: add 'middle' option for borderSkipped
* Split in 2
  • Loading branch information
kurkle committed Jul 21, 2021
1 parent cf951ac commit b32fb48
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 39 deletions.
1 change: 1 addition & 0 deletions docs/charts/bar.md
Expand Up @@ -157,6 +157,7 @@ Options are:

* `'start'`
* `'end'`
* `'middle'` (only valid on stacked bars: the borders between bars are skipped)
* `'bottom'`
* `'left'`
* `'top'`
Expand Down
2 changes: 1 addition & 1 deletion docs/configuration/elements.md
Expand Up @@ -77,7 +77,7 @@ Namespace: `options.elements.bar`, global bar options: `Chart.defaults.elements.
| `backgroundColor` | [`Color`](/general/colors.md) | `Chart.defaults.backgroundColor` | Bar fill color.
| `borderWidth` | `number` | `0` | Bar stroke width.
| `borderColor` | [`Color`](/general/colors.md) | `Chart.defaults.borderColor` | Bar stroke color.
| `borderSkipped` | `string` | `'start'` | Skipped (excluded) border: `'start'`, `'end'`, `'bottom'`, `'left'`, `'top'` or `'right'`.
| `borderSkipped` | `string` | `'start'` | Skipped (excluded) border: `'start'`, `'end'`, `'middle'`, `'bottom'`, `'left'`, `'top'`, `'right'` or `false`.
| `borderRadius` | `number`\|`object` | `0` | The bar border radius (in pixels).
| [`pointStyle`](#point-styles) | `string`\|`Image` | `'circle'` | Style of the point for legend.

Expand Down
71 changes: 69 additions & 2 deletions src/controllers/controller.bar.js
Expand Up @@ -177,6 +177,72 @@ function barSign(size, vScale, actualBase) {
return (vScale.isHorizontal() ? 1 : -1) * (vScale.min >= actualBase ? 1 : -1);
}

function borderProps(properties) {
let reverse, start, end, top, bottom;
if (properties.horizontal) {
reverse = properties.base > properties.x;
start = 'left';
end = 'right';
} else {
reverse = properties.base < properties.y;
start = 'bottom';
end = 'top';
}
if (reverse) {
top = 'end';
bottom = 'start';
} else {
top = 'start';
bottom = 'end';
}
return {start, end, reverse, top, bottom};
}

function setBorderSkipped(properties, options, stack, index) {
let edge = options.borderSkipped;
const res = {};

if (!edge) {
properties.borderSkipped = res;
return;
}

const {start, end, reverse, top, bottom} = borderProps(properties);

if (edge === 'middle' && stack) {
properties.enableBorderRadius = true;
if ((stack._top || 0) === index) {
edge = top;
} else if ((stack._bottom || 0) === index) {
edge = bottom;
} else {
res[parseEdge(bottom, start, end, reverse)] = true;
edge = top;
}
}

res[parseEdge(edge, start, end, reverse)] = true;
properties.borderSkipped = res;
}

function parseEdge(edge, a, b, reverse) {
if (reverse) {
edge = swap(edge, a, b);
edge = startEnd(edge, b, a);
} else {
edge = startEnd(edge, a, b);
}
return edge;
}

function swap(orig, v1, v2) {
return orig === v1 ? v2 : orig === v2 ? v1 : orig;
}

function startEnd(v, start, end) {
return v === 'start' ? start : v === 'end' ? end : v;
}

export default class BarController extends DatasetController {

/**
Expand Down Expand Up @@ -278,7 +344,7 @@ export default class BarController extends DatasetController {
updateElements(bars, start, count, mode) {
const me = this;
const reset = mode === 'reset';
const vScale = me._cachedMeta.vScale;
const {index, _cachedMeta: {vScale}} = me;
const base = vScale.getBasePixel();
const horizontal = vScale.isHorizontal();
const ruler = me._getRuler();
Expand All @@ -297,7 +363,7 @@ export default class BarController extends DatasetController {
const properties = {
horizontal,
base: vpixels.base,
enableBorderRadius: !stack || isFloatBar(parsed._custom) || (me.index === stack._top || me.index === stack._bottom),
enableBorderRadius: !stack || isFloatBar(parsed._custom) || (index === stack._top || index === stack._bottom),
x: horizontal ? vpixels.head : ipixels.center,
y: horizontal ? ipixels.center : vpixels.head,
height: horizontal ? ipixels.size : Math.abs(vpixels.size),
Expand All @@ -307,6 +373,7 @@ export default class BarController extends DatasetController {
if (includeOptions) {
properties.options = sharedOptions || me.resolveDataElementOptions(i, bars[i].active ? 'active' : mode);
}
setBorderSkipped(properties, properties.options || bars[i].options, stack, index);
me.updateElement(bars[i], i, properties, mode);
}
}
Expand Down
38 changes: 2 additions & 36 deletions src/elements/element.bar.js
Expand Up @@ -32,47 +32,13 @@ function getBarBounds(bar, useFinalPosition) {
return {left, top, right, bottom};
}

function parseBorderSkipped(bar) {
let edge = bar.options.borderSkipped;
const res = {};

if (!edge) {
return res;
}

edge = bar.horizontal
? parseEdge(edge, 'left', 'right', bar.base > bar.x)
: parseEdge(edge, 'bottom', 'top', bar.base < bar.y);

res[edge] = true;
return res;
}

function parseEdge(edge, a, b, reverse) {
if (reverse) {
edge = swap(edge, a, b);
edge = startEnd(edge, b, a);
} else {
edge = startEnd(edge, a, b);
}
return edge;
}

function swap(orig, v1, v2) {
return orig === v1 ? v2 : orig === v2 ? v1 : orig;
}

function startEnd(v, start, end) {
return v === 'start' ? start : v === 'end' ? end : v;
}

function skipOrLimit(skip, value, min, max) {
return skip ? 0 : _limitValue(value, min, max);
}

function parseBorderWidth(bar, maxW, maxH) {
const value = bar.options.borderWidth;
const skip = parseBorderSkipped(bar);
const skip = bar.borderSkipped;
const o = toTRBL(value);

return {
Expand All @@ -88,7 +54,7 @@ function parseBorderRadius(bar, maxW, maxH) {
const value = bar.options.borderRadius;
const o = toTRBLCorners(value);
const maxR = Math.min(maxW, maxH);
const skip = parseBorderSkipped(bar);
const skip = bar.borderSkipped;

// If the value is an object, assume the user knows what they are doing
// and apply as directed.
Expand Down
38 changes: 38 additions & 0 deletions test/fixtures/controller.bar/borderSkipped/middle.js
@@ -0,0 +1,38 @@
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: {
borderRadius: Number.MAX_VALUE,
borderSkipped: 'middle',
borderWidth: 2,
scales: {
x: {display: false, stacked: true},
y: {display: false, stacked: true}
}
}
},
options: {
canvas: {
height: 256,
width: 512
}
}
};
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit b32fb48

Please sign in to comment.