mirror of
https://github.com/chartjs/Chart.js.git
synced 2025-12-08 20:36:08 +00:00
Bar: add 'middle' option for borderSkipped (#9452)
* Bar: add 'middle' option for borderSkipped * Split in 2
This commit is contained in:
parent
cf951ac611
commit
b32fb48574
@ -157,6 +157,7 @@ Options are:
|
|||||||
|
|
||||||
* `'start'`
|
* `'start'`
|
||||||
* `'end'`
|
* `'end'`
|
||||||
|
* `'middle'` (only valid on stacked bars: the borders between bars are skipped)
|
||||||
* `'bottom'`
|
* `'bottom'`
|
||||||
* `'left'`
|
* `'left'`
|
||||||
* `'top'`
|
* `'top'`
|
||||||
|
|||||||
@ -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.
|
| `backgroundColor` | [`Color`](/general/colors.md) | `Chart.defaults.backgroundColor` | Bar fill color.
|
||||||
| `borderWidth` | `number` | `0` | Bar stroke width.
|
| `borderWidth` | `number` | `0` | Bar stroke width.
|
||||||
| `borderColor` | [`Color`](/general/colors.md) | `Chart.defaults.borderColor` | Bar stroke color.
|
| `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).
|
| `borderRadius` | `number`\|`object` | `0` | The bar border radius (in pixels).
|
||||||
| [`pointStyle`](#point-styles) | `string`\|`Image` | `'circle'` | Style of the point for legend.
|
| [`pointStyle`](#point-styles) | `string`\|`Image` | `'circle'` | Style of the point for legend.
|
||||||
|
|
||||||
|
|||||||
@ -177,6 +177,72 @@ function barSign(size, vScale, actualBase) {
|
|||||||
return (vScale.isHorizontal() ? 1 : -1) * (vScale.min >= actualBase ? 1 : -1);
|
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 {
|
export default class BarController extends DatasetController {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -278,7 +344,7 @@ export default class BarController extends DatasetController {
|
|||||||
updateElements(bars, start, count, mode) {
|
updateElements(bars, start, count, mode) {
|
||||||
const me = this;
|
const me = this;
|
||||||
const reset = mode === 'reset';
|
const reset = mode === 'reset';
|
||||||
const vScale = me._cachedMeta.vScale;
|
const {index, _cachedMeta: {vScale}} = me;
|
||||||
const base = vScale.getBasePixel();
|
const base = vScale.getBasePixel();
|
||||||
const horizontal = vScale.isHorizontal();
|
const horizontal = vScale.isHorizontal();
|
||||||
const ruler = me._getRuler();
|
const ruler = me._getRuler();
|
||||||
@ -297,7 +363,7 @@ export default class BarController extends DatasetController {
|
|||||||
const properties = {
|
const properties = {
|
||||||
horizontal,
|
horizontal,
|
||||||
base: vpixels.base,
|
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,
|
x: horizontal ? vpixels.head : ipixels.center,
|
||||||
y: horizontal ? ipixels.center : vpixels.head,
|
y: horizontal ? ipixels.center : vpixels.head,
|
||||||
height: horizontal ? ipixels.size : Math.abs(vpixels.size),
|
height: horizontal ? ipixels.size : Math.abs(vpixels.size),
|
||||||
@ -307,6 +373,7 @@ export default class BarController extends DatasetController {
|
|||||||
if (includeOptions) {
|
if (includeOptions) {
|
||||||
properties.options = sharedOptions || me.resolveDataElementOptions(i, bars[i].active ? 'active' : mode);
|
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);
|
me.updateElement(bars[i], i, properties, mode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,47 +32,13 @@ function getBarBounds(bar, useFinalPosition) {
|
|||||||
return {left, top, right, bottom};
|
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) {
|
function skipOrLimit(skip, value, min, max) {
|
||||||
return skip ? 0 : _limitValue(value, min, max);
|
return skip ? 0 : _limitValue(value, min, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseBorderWidth(bar, maxW, maxH) {
|
function parseBorderWidth(bar, maxW, maxH) {
|
||||||
const value = bar.options.borderWidth;
|
const value = bar.options.borderWidth;
|
||||||
const skip = parseBorderSkipped(bar);
|
const skip = bar.borderSkipped;
|
||||||
const o = toTRBL(value);
|
const o = toTRBL(value);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -88,7 +54,7 @@ function parseBorderRadius(bar, maxW, maxH) {
|
|||||||
const value = bar.options.borderRadius;
|
const value = bar.options.borderRadius;
|
||||||
const o = toTRBLCorners(value);
|
const o = toTRBLCorners(value);
|
||||||
const maxR = Math.min(maxW, maxH);
|
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
|
// If the value is an object, assume the user knows what they are doing
|
||||||
// and apply as directed.
|
// and apply as directed.
|
||||||
|
|||||||
38
test/fixtures/controller.bar/borderSkipped/middle.js
vendored
Normal file
38
test/fixtures/controller.bar/borderSkipped/middle.js
vendored
Normal file
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
BIN
test/fixtures/controller.bar/borderSkipped/middle.png
vendored
Normal file
BIN
test/fixtures/controller.bar/borderSkipped/middle.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
Loading…
x
Reference in New Issue
Block a user