support for multiple datasets added

This commit is contained in:
Axel Müller
2023-12-27 12:13:30 +01:00
parent 60280361b0
commit a36fa7cd2f
5 changed files with 128 additions and 83 deletions

View File

@@ -52,7 +52,7 @@
line [+1.3, .6, 2.4, -.34] line [+1.3, .6, 2.4, -.34]
</pre> </pre>
<h1>XY Charts Bar with multiple category</h1> <h1>XY Charts bar with single dataset</h1>
<pre class="mermaid"> <pre class="mermaid">
xychart-beta xychart-beta
title "Basic xychart with many categories" title "Basic xychart with many categories"
@@ -61,7 +61,25 @@
bar "sample bar" [52, 96, 35, 10, 87, 34, 67, 99] bar "sample bar" [52, 96, 35, 10, 87, 34, 67, 99]
</pre> </pre>
<h1>XY Charts line with multiple category</h1> <h1>XY Charts bar with multiple datasets</h1>
<pre class="mermaid">
xychart-beta
title "Basic xychart with multiple datasets"
x-axis "Relevant categories" [category1, "category 2", category3, category4, category5, category6, category7]
y-axis Animals 10 --> 200
bar [["dogs" [52, 96, 35, 10, 87, 34, 67, 99]],["cats" [15, 7, 23, 55, 11, 41, 26, 3]]]
</pre>
<h1>XY Charts bar horizontal with multiple datasets</h1>
<pre class="mermaid">
xychart-beta horizontal
title "Basic xychart with multiple datasets"
x-axis "Relevant categories" [category1, "category 2", category3, category4, category5, category6, category7]
y-axis Animals 10 --> 200
bar [["dogs" [52, 96, 35, 10, 87, 34, 67, 99]],["cats" [15, 7, 23, 55, 11, 41, 26, 3]]]
</pre>
<h1>XY Charts line single dataset</h1>
<pre class="mermaid"> <pre class="mermaid">
xychart-beta xychart-beta
title "Line chart with many category" title "Line chart with many category"
@@ -70,7 +88,7 @@
line "sample line" [52, 96, 35, 10, 87, 34, 67, 99] line "sample line" [52, 96, 35, 10, 87, 34, 67, 99]
</pre> </pre>
<h1>XY Charts category with large text</h1> <h1>XY Charts bar with large text</h1>
<pre class="mermaid"> <pre class="mermaid">
xychart-beta xychart-beta
title "Basic xychart with many categories with category overlap" title "Basic xychart with many categories with category overlap"

View File

@@ -3,7 +3,7 @@ import type { Axis } from '../axis/index.js';
export class BarPlot { export class BarPlot {
constructor( constructor(
private barData: BarPlotData, private barData: BarPlotData[],
private boundingRect: BoundingRect, private boundingRect: BoundingRect,
private xAxis: Axis, private xAxis: Axis,
private yAxis: Axis, private yAxis: Axis,
@@ -12,49 +12,58 @@ export class BarPlot {
) {} ) {}
getDrawableElement(): DrawableElem[] { getDrawableElement(): DrawableElem[] {
const finalData: [number, number][] = this.barData.data.map((d) => [ const offset = new Array(this.barData[0].data.length).fill(0);
this.xAxis.getScaleValue(d[0]), return this.barData.map((barData, dataIndex) => {
this.yAxis.getScaleValue(d[1]), const finalData: [number, number][] = barData.data.map((d) => [
]); this.xAxis.getScaleValue(d[0]),
this.yAxis.getScaleValue(d[1]),
]);
const barPaddingPercent = 0.05;
const barPaddingPercent = 0.05; const barWidth =
Math.min(this.xAxis.getAxisOuterPadding() * 2, this.xAxis.getTickDistance()) *
const barWidth = (1 - barPaddingPercent);
Math.min(this.xAxis.getAxisOuterPadding() * 2, this.xAxis.getTickDistance()) * const barWidthHalf = barWidth / 2;
(1 - barPaddingPercent);
const barWidthHalf = barWidth / 2; if (this.orientation === 'horizontal') {
return {
if (this.orientation === 'horizontal') { groupTexts: ['plot', `bar-plot-${this.plotIndex}-${dataIndex}`],
return [ type: 'rect',
{ data: finalData.map((data, index) => {
groupTexts: ['plot', `bar-plot-${this.plotIndex}`], const x = offset[index] + this.boundingRect.x;
const width = data[1] - this.boundingRect.x;
offset[index] += width;
return {
x,
y: data[0] - barWidthHalf,
height: barWidth,
width,
fill: barData.fill,
strokeWidth: 0,
strokeFill: barData.fill,
}
}),
};
}
return {
groupTexts: ['plot', `bar-plot-${this.plotIndex}-${dataIndex}`],
type: 'rect', type: 'rect',
data: finalData.map((data) => ({ data: finalData.map((data, index) => {
x: this.boundingRect.x, const y = data[1] - offset[index];
y: data[0] - barWidthHalf, const height = this.boundingRect.y + this.boundingRect.height - data[1];
height: barWidth, offset[index] += height;
width: data[1] - this.boundingRect.x, return {
fill: this.barData.fill, x: data[0] - barWidthHalf,
strokeWidth: 0, y,
strokeFill: this.barData.fill, width: barWidth,
})), height,
}, fill: barData.fill,
]; strokeWidth: 0,
} strokeFill: barData.fill,
return [ };
{ }),
groupTexts: ['plot', `bar-plot-${this.plotIndex}`], };
type: 'rect', });
data: finalData.map((data) => ({
x: data[0] - barWidthHalf,
y: data[1],
width: barWidth,
height: this.boundingRect.y + this.boundingRect.height - data[1],
fill: this.barData.fill,
strokeWidth: 0,
strokeFill: this.barData.fill,
})),
},
];
} }
} }

View File

@@ -6,6 +6,8 @@ import type {
Point, Point,
XYChartThemeConfig, XYChartThemeConfig,
XYChartConfig, XYChartConfig,
BarPlotData,
LinePlotData,
} from '../../interfaces.js'; } from '../../interfaces.js';
import type { Axis } from '../axis/index.js'; import type { Axis } from '../axis/index.js';
import type { ChartComponent } from '../../interfaces.js'; import type { ChartComponent } from '../../interfaces.js';
@@ -55,34 +57,31 @@ export class BasePlot implements Plot {
throw Error('Axes must be passed to render Plots'); throw Error('Axes must be passed to render Plots');
} }
const drawableElem: DrawableElem[] = []; const drawableElem: DrawableElem[] = [];
for (const [i, plot] of this.chartData.plots.entries()) { const linePlots = this.chartData.plots.filter(plot => plot.type === 'line') as LinePlotData[];
switch (plot.type) { const barPlots = this.chartData.plots.filter(plot => plot.type === 'bar') as BarPlotData[];
case 'line':
{ let plotIndex = 0;
const linePlot = new LinePlot( if(linePlots.length) {
plot, const linePlot = new LinePlot(
this.xAxis, linePlots[0],
this.yAxis, this.xAxis,
this.chartConfig.chartOrientation, this.yAxis,
i this.chartConfig.chartOrientation,
); plotIndex
drawableElem.push(...linePlot.getDrawableElement()); );
} drawableElem.push(...linePlot.getDrawableElement());
break; }
case 'bar': if(barPlots.length) {
{ const barPlot = new BarPlot(
const barPlot = new BarPlot( barPlots,
plot, this.boundingRect,
this.boundingRect, this.xAxis,
this.xAxis, this.yAxis,
this.yAxis, this.chartConfig.chartOrientation,
this.chartConfig.chartOrientation, plotIndex
i );
); drawableElem.push(...barPlot.getDrawableElement());
drawableElem.push(...barPlot.getDrawableElement()); plotIndex++;
}
break;
}
} }
return drawableElem; return drawableElem;
} }

View File

@@ -102,13 +102,28 @@ statement
| Y_AXIS parseYAxis | Y_AXIS parseYAxis
| LINE plotData { yy.setLineData({text: '', type: 'text'}, $plotData); } | LINE plotData { yy.setLineData({text: '', type: 'text'}, $plotData); }
| LINE text plotData { yy.setLineData($text, $plotData); } | LINE text plotData { yy.setLineData($text, $plotData); }
| BAR plotData { yy.setBarData({text: '', type: 'text'}, $plotData); } | BAR datasets { yy.setBarData($datasets); }
| BAR text plotData { yy.setBarData($text, $plotData); }
| acc_title acc_title_value { $$=$acc_title_value.trim();yy.setAccTitle($$); } | acc_title acc_title_value { $$=$acc_title_value.trim();yy.setAccTitle($$); }
| acc_descr acc_descr_value { $$=$acc_descr_value.trim();yy.setAccDescription($$); } | acc_descr acc_descr_value { $$=$acc_descr_value.trim();yy.setAccDescription($$); }
| acc_descr_multiline_value { $$=$acc_descr_multiline_value.trim();yy.setAccDescription($$); } | acc_descr_multiline_value { $$=$acc_descr_multiline_value.trim();yy.setAccDescription($$); }
; ;
datasets
: SQUARE_BRACES_START datasetBraced COMMA datasets SQUARE_BRACES_END { $$ = [$datasetBraced, ...$datasets] }
| SQUARE_BRACES_START datasetBraced SQUARE_BRACES_END { $$ = [$datasetBraced] }
| datasetBraced { $$ = [$datasetBraced] }
| dataset { $$ = [$dataset] }
;
datasetBraced
: SQUARE_BRACES_START dataset SQUARE_BRACES_END { $$ = $dataset }
;
dataset
: plotData { $$ = ['', $plotData] }
| text plotData { $$ = [$text, $plotData] }
;
plotData plotData
: SQUARE_BRACES_START commaSeparatedNumbers SQUARE_BRACES_END { $$ = $commaSeparatedNumbers } : SQUARE_BRACES_START commaSeparatedNumbers SQUARE_BRACES_END { $$ = $commaSeparatedNumbers }
; ;

View File

@@ -169,14 +169,18 @@ function setLineData(title: NormalTextType, data: number[]) {
plotIndex++; plotIndex++;
} }
function setBarData(title: NormalTextType, data: number[]) { type NamedDataset = [title: NormalTextType, data: number[]];
const plotData = transformDataWithoutCategory(data);
xyChartData.plots.push({ function setBarData(datasets: NamedDataset[]) {
type: 'bar', datasets.forEach(dataset => {
fill: getPlotColorFromPalette(plotIndex), const plotData = transformDataWithoutCategory(dataset[1]);
data: plotData, xyChartData.plots.push({
type: 'bar',
fill: getPlotColorFromPalette(plotIndex),
data: plotData,
});
plotIndex++;
}); });
plotIndex++;
} }
function getDrawableElem(): DrawableElem[] { function getDrawableElem(): DrawableElem[] {