Skip to content

Commit

Permalink
feat: accumulate-relative stacked bar chart stack mode (#1375)
Browse files Browse the repository at this point in the history
new stack mode was implemented

closes #1167
  • Loading branch information
dangreen authored Nov 3, 2022
1 parent f94e559 commit ce13067
Show file tree
Hide file tree
Showing 10 changed files with 93 additions and 17 deletions.
4 changes: 2 additions & 2 deletions .size-limit.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
},
{
"path": "dist/index.cjs",
"limit": "7.35 kB",
"limit": "7.40 kB",
"import": "{ BarChart }"
},
{
Expand All @@ -18,7 +18,7 @@
},
{
"path": "dist/index.js",
"limit": "7.3 kB",
"limit": "7.4 kB",
"import": "{ BarChart }"
},
{
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ import type {
- [Multi-line labels](http://codesandbox.io/s/github/chartist-js/chartist/main/sandboxes/bar/multiline)
- [Overlapping bars on mobile](http://codesandbox.io/s/github/chartist-js/chartist/main/sandboxes/bar/overlapping-bars)
- [Stacked bar chart](http://codesandbox.io/s/github/chartist-js/chartist/main/sandboxes/bar/stacked)
- [Stacked bar chart with accumulate-relative stack mode](http://codesandbox.io/s/github/chartist-js/chartist/main/sandboxes/bar/stacked-accumulate-relative)
- [Add peak circles using the draw events](http://codesandbox.io/s/github/chartist-js/chartist/main/sandboxes/bar/with-circle-modify-drawing)

</details>
Expand Down
9 changes: 9 additions & 0 deletions sandboxes/bar/stacked-accumulate-relative/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<!DOCTYPE html>
<html>
<head>
<script defer src="./index.ts"></script>
</head>
<body>
<div id="chart" style="height: 50vh"></div>
</body>
</html>
17 changes: 17 additions & 0 deletions sandboxes/bar/stacked-accumulate-relative/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import 'chartist/dist/index.css';
import { BarChart } from 'chartist';

new BarChart(
'#chart',
{
labels: ['Monday', 'Tuesday', 'Wednesday', 'Thursday'],
series: [
[5, 4, -3, -5],
[5, -4, 3, -5]
]
},
{
stackBars: true,
stackMode: 'accumulate-relative'
}
);
8 changes: 8 additions & 0 deletions sandboxes/bar/stacked-accumulate-relative/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "bar-stacked",
"description": "Stacked bar chart with accumulate-relative stack mode",
"main": "index.ts",
"dependencies": {
"chartist": "^1.0.0"
}
}
6 changes: 6 additions & 0 deletions sandboxes/bar/stacked-accumulate-relative/sandbox.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"infiniteLoopProtection": true,
"hardReloadOnChange": true,
"view": "browser",
"template": "parcel"
}
21 changes: 21 additions & 0 deletions src/charts/BarChart/BarChart.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -424,3 +424,24 @@ export function PeakCircles() {

return root;
}

export function AccumulateRelativeStack() {
const root = document.createElement('div');

new BarChart(
root,
{
labels: ['Monday', 'Tuesday', 'Wednesday', 'Thursday'],
series: [
[5, 4, -3, -5],
[5, -4, 3, -5]
]
},
{
stackBars: true,
stackMode: 'accumulate-relative'
}
);

return root;
}
39 changes: 26 additions & 13 deletions src/charts/BarChart/BarChart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,9 @@ const defaultOptions = {
seriesBarDistance: 15,
// If set to true this property will cause the series bars to be stacked. Check the `stackMode` option for further stacking options.
stackBars: false,
// If set to 'overlap' this property will force the stacked bars to draw from the zero line.
// If set to true this property will force the stacked bars to draw from the zero line.
// If set to 'accumulate' this property will form a total for each series point. This will also influence the y-axis and the overall bounds of the chart. In stacked mode the seriesBarDistance property will have no effect.
// If set to 'accumulate-relative' positive and negative values will be handled separately.
stackMode: 'accumulate' as const,
// Inverts the axes of the bar chart in order to draw a horizontal bar chart. Be aware that you also need to invert your axis settings as the Y Axis will now display the labels and the X Axis the values.
horizontalBars: false,
Expand Down Expand Up @@ -344,8 +345,13 @@ export class BarChart extends BaseChart<BarChartEventsTypes> {
const zeroPoint = options.horizontalBars
? chartRect.x1 + valueAxis.projectValue(0)
: chartRect.y1 - valueAxis.projectValue(0);
const isAccumulateStackMode = options.stackMode === 'accumulate';
const isAccumulateRelativeStackMode =
options.stackMode === 'accumulate-relative';
// Used to track the screen coordinates of stacked bars
const stackedBarValues: number[] = [];
const posStackedBarValues: number[] = [];
const negStackedBarValues: number[] = [];
let stackedBarValues = posStackedBarValues;

labelAxis.createGridAndLabels(
gridGroup,
Expand Down Expand Up @@ -428,6 +434,8 @@ export class BarChart extends BaseChart<BarChartEventsTypes> {
);

normalizedData.series[seriesIndex].forEach((value, valueIndex) => {
const valueX = safeHasProperty(value, 'x') && value.x;
const valueY = safeHasProperty(value, 'y') && value.y;
let labelAxisValueIndex;
// We need to set labelAxisValueIndex based on some options combinations
if (options.distributeSeries && !options.stackBars) {
Expand All @@ -450,14 +458,14 @@ export class BarChart extends BaseChart<BarChartEventsTypes> {
x:
chartRect.x1 +
valueAxis.projectValue(
safeHasProperty(value, 'x') ? value.x : 0,
valueX || 0,
valueIndex,
normalizedData.series[seriesIndex]
),
y:
chartRect.y1 -
labelAxis.projectValue(
safeHasProperty(value, 'y') ? value.y : 0,
valueY || 0,
labelAxisValueIndex,
normalizedData.series[seriesIndex]
)
Expand All @@ -467,14 +475,14 @@ export class BarChart extends BaseChart<BarChartEventsTypes> {
x:
chartRect.x1 +
labelAxis.projectValue(
safeHasProperty(value, 'x') ? value.x : 0,
valueX || 0,
labelAxisValueIndex,
normalizedData.series[seriesIndex]
),
y:
chartRect.y1 -
valueAxis.projectValue(
safeHasProperty(value, 'y') ? value.y : 0,
valueY || 0,
valueIndex,
normalizedData.series[seriesIndex]
)
Expand All @@ -500,6 +508,14 @@ export class BarChart extends BaseChart<BarChartEventsTypes> {
(options.horizontalBars ? -1 : 1);
}

// distinguish between positive and negative values in relative stack mode
if (isAccumulateRelativeStackMode) {
stackedBarValues =
valueY >= 0 || valueX >= 0
? posStackedBarValues
: negStackedBarValues;
}

// Enter value in stacked bar values used to remember previous screen value for stacking up bars
const previousStack = stackedBarValues[valueIndex] || zeroPoint;
stackedBarValues[valueIndex] =
Expand All @@ -517,7 +533,9 @@ export class BarChart extends BaseChart<BarChartEventsTypes> {

if (
options.stackBars &&
(options.stackMode === 'accumulate' || !options.stackMode)
(isAccumulateStackMode ||
isAccumulateRelativeStackMode ||
!options.stackMode)
) {
// Stack mode: accumulate (default)
// If bars are stacked we use the stackedBarValues reference and otherwise base all bars off the zero line
Expand Down Expand Up @@ -558,12 +576,7 @@ export class BarChart extends BaseChart<BarChartEventsTypes> {
const bar = seriesElement
.elem('line', positions, options.classNames.bar)
.attr({
'ct:value': [
safeHasProperty(value, 'x') && value.x,
safeHasProperty(value, 'y') && value.y
]
.filter(isNumeric)
.join(','),
'ct:value': [valueX, valueY].filter(isNumeric).join(','),
'ct:meta': serialize(metaData)
});

Expand Down
5 changes: 3 additions & 2 deletions src/charts/BarChart/BarChart.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,11 @@ export interface BarChartOptions<
*/
stackBars?: boolean;
/**
* If set to 'overlap' this property will force the stacked bars to draw from the zero line.
* If set to true this property will force the stacked bars to draw from the zero line.
* If set to 'accumulate' this property will form a total for each series point. This will also influence the y-axis and the overall bounds of the chart. In stacked mode the seriesBarDistance property will have no effect.
* If set to 'accumulate-relative' positive and negative values will be handled separately.
*/
stackMode?: 'accumulate' | boolean;
stackMode?: 'accumulate' | 'accumulate-relative' | boolean;
/**
* Inverts the axes of the bar chart in order to draw a horizontal bar chart. Be aware that you also need to invert your axis settings as the Y Axis will now display the labels and the X Axis the values.
*/
Expand Down
Loading
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 ce13067

Please sign in to comment.