mirror of
https://github.com/chartjs/Chart.js.git
synced 2025-12-08 20:36:08 +00:00
Add option to turn off grouping of bar datasets (#8641)
* Add option to turn off grouping of bar datasets * Disregard time offset
This commit is contained in:
parent
f744c3bde6
commit
85123ac074
@ -173,6 +173,7 @@ The bar chart accepts the following configuration from the associated dataset op
|
||||
| `categoryPercentage` | `number` | `0.8` | Percent (0-1) of the available width each category should be within the sample width. [more...](#barpercentage-vs-categorypercentage)
|
||||
| `barThickness` | `number`\|`string` | | Manually set width of each bar in pixels. If set to `'flex'`, it computes "optimal" sample widths that globally arrange bars side by side. If not set (default), bars are equally sized based on the smallest interval. [more...](#barthickness)
|
||||
| `base` | `number` | | Base value for the bar in data units along the value axis. If not set, defaults to the value axis base value.
|
||||
| `grouped` | `boolean` | `true` | Should the bars be grouped on index axis. When `true`, all the datasets at same index value will be placed next to each other centering on that index value. When `false`, each bar is placed on its actual index-axis value.
|
||||
| `maxBarThickness` | `number` | | Set this to ensure that bars are not sized thicker than this.
|
||||
| `minBarLength` | `number` | | Set this to ensure that bars have a minimum length in pixels.
|
||||
|
||||
|
||||
@ -255,9 +255,9 @@ export default class BarController extends DatasetController {
|
||||
updateElements(bars, start, count, mode) {
|
||||
const me = this;
|
||||
const reset = mode === 'reset';
|
||||
const vscale = me._cachedMeta.vScale;
|
||||
const base = vscale.getBasePixel();
|
||||
const horizontal = vscale.isHorizontal();
|
||||
const vScale = me._cachedMeta.vScale;
|
||||
const base = vScale.getBasePixel();
|
||||
const horizontal = vScale.isHorizontal();
|
||||
const ruler = me._getRuler();
|
||||
const firstOpts = me.resolveDataElementOptions(start, mode);
|
||||
const sharedOptions = me.getSharedOptions(firstOpts);
|
||||
@ -266,14 +266,14 @@ export default class BarController extends DatasetController {
|
||||
me.updateSharedOptions(sharedOptions, mode, firstOpts);
|
||||
|
||||
for (let i = start; i < start + count; i++) {
|
||||
const vpixels = me._calculateBarValuePixels(i);
|
||||
const vpixels = reset ? {base, head: base} : me._calculateBarValuePixels(i);
|
||||
const ipixels = me._calculateBarIndexPixels(i, ruler);
|
||||
|
||||
const properties = {
|
||||
horizontal,
|
||||
base: reset ? base : vpixels.base,
|
||||
x: horizontal ? reset ? base : vpixels.head : ipixels.center,
|
||||
y: horizontal ? ipixels.center : reset ? base : vpixels.head,
|
||||
base: vpixels.base,
|
||||
x: horizontal ? vpixels.head : ipixels.center,
|
||||
y: horizontal ? ipixels.center : vpixels.head,
|
||||
height: horizontal ? ipixels.size : undefined,
|
||||
width: horizontal ? undefined : ipixels.size
|
||||
};
|
||||
@ -370,6 +370,7 @@ export default class BarController extends DatasetController {
|
||||
*/
|
||||
_getRuler() {
|
||||
const me = this;
|
||||
const opts = me.options;
|
||||
const meta = me._cachedMeta;
|
||||
const iScale = meta.iScale;
|
||||
const pixels = [];
|
||||
@ -379,11 +380,8 @@ export default class BarController extends DatasetController {
|
||||
pixels.push(iScale.getPixelForValue(me.getParsed(i)[iScale.axis], i));
|
||||
}
|
||||
|
||||
// Note: a potential optimization would be to skip computing this
|
||||
// only if the barThickness option is defined
|
||||
// Since a scriptable option may return null or undefined that
|
||||
// means the option would have to be of type number
|
||||
const min = computeMinSampleSize(iScale);
|
||||
const barThickness = opts.barThickness;
|
||||
const min = barThickness || computeMinSampleSize(iScale);
|
||||
|
||||
return {
|
||||
min,
|
||||
@ -391,7 +389,10 @@ export default class BarController extends DatasetController {
|
||||
start: iScale._startPixel,
|
||||
end: iScale._endPixel,
|
||||
stackCount: me._getStackCount(),
|
||||
scale: iScale
|
||||
scale: iScale,
|
||||
grouped: opts.grouped,
|
||||
// bar thickness ratio used for non-grouped bars
|
||||
ratio: barThickness ? 1 : opts.categoryPercentage * opts.barPercentage
|
||||
};
|
||||
}
|
||||
|
||||
@ -459,17 +460,24 @@ export default class BarController extends DatasetController {
|
||||
*/
|
||||
_calculateBarIndexPixels(index, ruler) {
|
||||
const me = this;
|
||||
const scale = ruler.scale;
|
||||
const options = me.options;
|
||||
const stackCount = options.skipNull ? me._getStackCount(index) : ruler.stackCount;
|
||||
const range = options.barThickness === 'flex'
|
||||
? computeFlexCategoryTraits(index, ruler, options, stackCount)
|
||||
: computeFitCategoryTraits(index, ruler, options, stackCount);
|
||||
const maxBarThickness = valueOrDefault(options.maxBarThickness, Infinity);
|
||||
let center, size;
|
||||
if (ruler.grouped) {
|
||||
const stackCount = options.skipNull ? me._getStackCount(index) : ruler.stackCount;
|
||||
const range = options.barThickness === 'flex'
|
||||
? computeFlexCategoryTraits(index, ruler, options, stackCount)
|
||||
: computeFitCategoryTraits(index, ruler, options, stackCount);
|
||||
|
||||
const stackIndex = me._getStackIndex(me.index, me._cachedMeta.stack);
|
||||
const center = range.start + (range.chunk * stackIndex) + (range.chunk / 2);
|
||||
const size = Math.min(
|
||||
valueOrDefault(options.maxBarThickness, Infinity),
|
||||
range.chunk * range.ratio);
|
||||
const stackIndex = me._getStackIndex(me.index, me._cachedMeta.stack);
|
||||
center = range.start + (range.chunk * stackIndex) + (range.chunk / 2);
|
||||
size = Math.min(maxBarThickness, range.chunk * range.ratio);
|
||||
} else {
|
||||
// For non-grouped bar charts, exact pixel values are used
|
||||
center = scale.getPixelForValue(me.getParsed(index)[scale.axis], index);
|
||||
size = Math.min(maxBarThickness, ruler.min * ruler.ratio);
|
||||
}
|
||||
|
||||
return {
|
||||
base: center - size / 2,
|
||||
@ -512,6 +520,7 @@ BarController.defaults = {
|
||||
|
||||
categoryPercentage: 0.8,
|
||||
barPercentage: 0.9,
|
||||
grouped: true,
|
||||
|
||||
animations: {
|
||||
numbers: {
|
||||
|
||||
134
test/fixtures/controller.bar/not-grouped/on-time.js
vendored
Normal file
134
test/fixtures/controller.bar/not-grouped/on-time.js
vendored
Normal file
@ -0,0 +1,134 @@
|
||||
const data1 = [
|
||||
{
|
||||
x: '2017-11-02T20:30:00',
|
||||
y: 27
|
||||
},
|
||||
{
|
||||
x: '2017-11-03T20:53:00',
|
||||
y: 30
|
||||
},
|
||||
{
|
||||
x: '2017-11-06T05:46:00',
|
||||
y: 19
|
||||
},
|
||||
{
|
||||
x: '2017-11-06T21:03:00',
|
||||
y: 28
|
||||
},
|
||||
{
|
||||
x: '2017-11-07T20:49:00',
|
||||
y: 29
|
||||
},
|
||||
{
|
||||
x: '2017-11-08T21:52:00',
|
||||
y: 33
|
||||
}
|
||||
];
|
||||
|
||||
const data2 = [
|
||||
{
|
||||
x: '2017-11-03T13:07:00',
|
||||
y: 45
|
||||
},
|
||||
{
|
||||
x: '2017-11-04T04:50:00',
|
||||
y: 40
|
||||
},
|
||||
{
|
||||
x: '2017-11-06T12:48:00',
|
||||
y: 38
|
||||
},
|
||||
{
|
||||
x: '2017-11-07T12:28:00',
|
||||
y: 42
|
||||
},
|
||||
{
|
||||
x: '2017-11-08T12:45:00',
|
||||
y: 51
|
||||
},
|
||||
{
|
||||
x: '2017-11-09T05:23:00',
|
||||
y: 57
|
||||
}
|
||||
];
|
||||
|
||||
const data3 = [
|
||||
{
|
||||
x: '2017-11-03T16:30:00',
|
||||
y: 32
|
||||
},
|
||||
{
|
||||
x: '2017-11-04T11:50:00',
|
||||
y: 34
|
||||
},
|
||||
{
|
||||
x: '2017-11-06T18:30:00',
|
||||
y: 28
|
||||
},
|
||||
{
|
||||
x: '2017-11-07T15:51:00',
|
||||
y: 31
|
||||
},
|
||||
{
|
||||
x: '2017-11-08T17:27:00',
|
||||
y: 36
|
||||
},
|
||||
{
|
||||
x: '2017-11-09T06:53:00',
|
||||
y: 31
|
||||
}
|
||||
];
|
||||
|
||||
module.exports = {
|
||||
description: 'https://github.com/chartjs/Chart.js/issues/5139',
|
||||
config: {
|
||||
type: 'bar',
|
||||
data: {
|
||||
datasets: [
|
||||
{
|
||||
data: data1,
|
||||
backgroundColor: 'rgb(0,0,255)',
|
||||
},
|
||||
{
|
||||
data: data2,
|
||||
backgroundColor: 'rgb(255,0,0)',
|
||||
},
|
||||
{
|
||||
data: data3,
|
||||
backgroundColor: 'rgb(0,255,0)',
|
||||
},
|
||||
]
|
||||
},
|
||||
options: {
|
||||
barThickness: 10,
|
||||
grouped: false,
|
||||
scales: {
|
||||
x: {
|
||||
bounds: 'ticks',
|
||||
type: 'time',
|
||||
offset: false,
|
||||
position: 'bottom',
|
||||
display: true,
|
||||
time: {
|
||||
isoWeekday: true,
|
||||
unit: 'day'
|
||||
},
|
||||
grid: {
|
||||
offset: false
|
||||
}
|
||||
},
|
||||
y: {
|
||||
beginAtZero: true,
|
||||
display: false
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
options: {
|
||||
spriteText: true,
|
||||
canvas: {
|
||||
width: 1000,
|
||||
height: 300
|
||||
}
|
||||
}
|
||||
};
|
||||
BIN
test/fixtures/controller.bar/not-grouped/on-time.png
vendored
Normal file
BIN
test/fixtures/controller.bar/not-grouped/on-time.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
Loading…
x
Reference in New Issue
Block a user