From 547a22edefa60e89ae652428fa22a7c4aa1c397f Mon Sep 17 00:00:00 2001 From: Subhash Halder Date: Thu, 15 Jun 2023 00:04:48 +0530 Subject: [PATCH] Added support for bar plot --- .../xychart/chartBuilder/Interfaces.ts | 29 +++----------- .../xychart/chartBuilder/Orchestrator.ts | 2 +- .../chartBuilder/components/ChartTitle.ts | 2 +- .../chartBuilder/components/Interfaces.ts | 7 ---- .../chartBuilder/components/axis/BaseAxis.ts | 13 +++++- .../chartBuilder/components/axis/index.ts | 5 ++- .../chartBuilder/components/plot/BarPlot.ts | 40 +++++++++++++++++++ .../chartBuilder/components/plot/index.ts | 8 +++- .../diagrams/xychart/chartBuilder/index.ts | 8 ++++ 9 files changed, 77 insertions(+), 37 deletions(-) delete mode 100644 packages/mermaid/src/diagrams/xychart/chartBuilder/components/Interfaces.ts create mode 100644 packages/mermaid/src/diagrams/xychart/chartBuilder/components/plot/BarPlot.ts diff --git a/packages/mermaid/src/diagrams/xychart/chartBuilder/Interfaces.ts b/packages/mermaid/src/diagrams/xychart/chartBuilder/Interfaces.ts index 51350ca25..c7a924edd 100644 --- a/packages/mermaid/src/diagrams/xychart/chartBuilder/Interfaces.ts +++ b/packages/mermaid/src/diagrams/xychart/chartBuilder/Interfaces.ts @@ -1,19 +1,12 @@ export enum ChartPlotEnum { LINE = 'line', + BAR = 'bar', } -export enum ChartLayoutElem { - NULL = 'null', - CHART = 'chart', - TITLE = 'title', - XAXISLABEL = 'xaxislabel', - XAXISTITLE = 'xaxistitle', - YAXISLABEL = 'yaxislabel', - YAXISTITLE = 'yaxistitle', -} -export enum XYChartYAxisPosition { - LEFT = 'left', - RIGHT = 'right', +export interface ChartComponent { + calculateSpace(availableSpace: Dimension): Dimension; + setBoundingBoxXY(point: Point): void; + getDrawableElements(): DrawableElem[]; } export enum OrientationEnum { @@ -21,16 +14,6 @@ export enum OrientationEnum { HORIZONTAL = 'horizontal', } -export type ChartLayout = ChartLayoutElem[][]; - -export type VisibilityOption = { - chartTitle: boolean; - xAxisTitle: boolean; - xAxisLabel: boolean; - yAxisTitle: boolean; - yAxisLabel: boolean; -}; - export interface AxisConfig { showLabel: boolean; labelFontSize: number; @@ -64,7 +47,7 @@ export interface XYChartConfig { export type SimplePlotDataType = [string | number, number][]; export interface LinePlotData { - type: ChartPlotEnum.LINE; + type: ChartPlotEnum.LINE | ChartPlotEnum.BAR; data: SimplePlotDataType; } diff --git a/packages/mermaid/src/diagrams/xychart/chartBuilder/Orchestrator.ts b/packages/mermaid/src/diagrams/xychart/chartBuilder/Orchestrator.ts index dce2cefe9..25e52cf24 100644 --- a/packages/mermaid/src/diagrams/xychart/chartBuilder/Orchestrator.ts +++ b/packages/mermaid/src/diagrams/xychart/chartBuilder/Orchestrator.ts @@ -1,7 +1,7 @@ import { log } from '../../../logger.js'; import { DrawableElem, XYChartConfig, XYChartData } from './Interfaces.js'; import { getChartTitleComponent } from './components/ChartTitle.js'; -import { ChartComponent } from './components/Interfaces.js'; +import { ChartComponent } from './Interfaces.js'; import { IAxis, getAxis } from './components/axis/index.js'; import { IPlot, getPlotComponent } from './components/plot/index.js'; diff --git a/packages/mermaid/src/diagrams/xychart/chartBuilder/components/ChartTitle.ts b/packages/mermaid/src/diagrams/xychart/chartBuilder/components/ChartTitle.ts index f02d7b05f..46a1b51d0 100644 --- a/packages/mermaid/src/diagrams/xychart/chartBuilder/components/ChartTitle.ts +++ b/packages/mermaid/src/diagrams/xychart/chartBuilder/components/ChartTitle.ts @@ -8,7 +8,7 @@ import { Point, OrientationEnum, } from '../Interfaces.js'; -import { ChartComponent } from './Interfaces.js'; +import { ChartComponent } from '../Interfaces.js'; export class ChartTitle implements ChartComponent { private boundingRect: BoundingRect; diff --git a/packages/mermaid/src/diagrams/xychart/chartBuilder/components/Interfaces.ts b/packages/mermaid/src/diagrams/xychart/chartBuilder/components/Interfaces.ts deleted file mode 100644 index 92f27986b..000000000 --- a/packages/mermaid/src/diagrams/xychart/chartBuilder/components/Interfaces.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { Dimension, DrawableElem, OrientationEnum, Point } from '../Interfaces.js'; - -export interface ChartComponent { - calculateSpace(availableSpace: Dimension): Dimension; - setBoundingBoxXY(point: Point): void; - getDrawableElements(): DrawableElem[]; -} diff --git a/packages/mermaid/src/diagrams/xychart/chartBuilder/components/axis/BaseAxis.ts b/packages/mermaid/src/diagrams/xychart/chartBuilder/components/axis/BaseAxis.ts index f6ed16caf..c341bd451 100644 --- a/packages/mermaid/src/diagrams/xychart/chartBuilder/components/axis/BaseAxis.ts +++ b/packages/mermaid/src/diagrams/xychart/chartBuilder/components/axis/BaseAxis.ts @@ -41,6 +41,11 @@ export abstract class BaseAxis implements IAxis { abstract getTickValues(): Array; + getTickInnerPadding(): number { + return this.innerPadding * 2; + // return Math.abs(this.range[0] - this.range[1]) / this.getTickValues().length; + } + private getLabelDimension(): Dimension { return this.textDimensionCalculator.getDimension( this.getTickValues().map((tick) => tick.toString()), @@ -162,7 +167,9 @@ export abstract class BaseAxis implements IAxis { type: 'path', groupTexts: ['left-axis', 'ticks'], data: this.getTickValues().map((tick) => ({ - path: `M ${x},${this.getScaleValue(tick)} L ${x - this.axisConfig.tickLength},${this.getScaleValue(tick)}`, + path: `M ${x},${this.getScaleValue(tick)} L ${ + x - this.axisConfig.tickLength + },${this.getScaleValue(tick)}`, strokeFill: this.axisConfig.tickFill, strokeWidth: this.axisConfig.tickWidth, })), @@ -212,7 +219,9 @@ export abstract class BaseAxis implements IAxis { type: 'path', groupTexts: ['bottom-axis', 'ticks'], data: this.getTickValues().map((tick) => ({ - path: `M ${this.getScaleValue(tick)},${y} L ${this.getScaleValue(tick)},${y + this.axisConfig.tickLength}`, + path: `M ${this.getScaleValue(tick)},${y} L ${this.getScaleValue(tick)},${ + y + this.axisConfig.tickLength + }`, strokeFill: this.axisConfig.tickFill, strokeWidth: this.axisConfig.tickWidth, })), diff --git a/packages/mermaid/src/diagrams/xychart/chartBuilder/components/axis/index.ts b/packages/mermaid/src/diagrams/xychart/chartBuilder/components/axis/index.ts index 1972ef2c5..dafa91878 100644 --- a/packages/mermaid/src/diagrams/xychart/chartBuilder/components/axis/index.ts +++ b/packages/mermaid/src/diagrams/xychart/chartBuilder/components/axis/index.ts @@ -5,15 +5,16 @@ import { LinearAxisDataType } from '../../Interfaces.js'; import { TextDimensionCalculator } from '../../TextDimensionCalculator.js'; -import { ChartComponent } from '../Interfaces.js'; +import { ChartComponent } from '../../Interfaces.js'; import { BandAxis } from './BandAxis.js'; import { LinearAxis } from './LinearAxis.js'; -export type AxisPosition = 'left' | 'bottom'; +export type AxisPosition = 'left' | 'bottom' | 'top' | 'bottom'; export interface IAxis extends ChartComponent { getScaleValue(value: string | number): number; setAxisPosition(axisPosition: AxisPosition): void; + getTickInnerPadding(): number; setRange(range: [number, number]): void; } diff --git a/packages/mermaid/src/diagrams/xychart/chartBuilder/components/plot/BarPlot.ts b/packages/mermaid/src/diagrams/xychart/chartBuilder/components/plot/BarPlot.ts new file mode 100644 index 000000000..76187466b --- /dev/null +++ b/packages/mermaid/src/diagrams/xychart/chartBuilder/components/plot/BarPlot.ts @@ -0,0 +1,40 @@ +import { line } from 'd3'; +import { BoundingRect, DrawableElem, SimplePlotDataType } from '../../Interfaces.js'; +import { IAxis } from '../axis/index.js'; + +export class BarPlot { + constructor( + private data: SimplePlotDataType, + private boundingRect: BoundingRect, + private xAxis: IAxis, + private yAxis: IAxis + ) {} + + getDrawableElement(): DrawableElem[] { + const finalData: [number, number][] = this.data.map((d) => [ + this.xAxis.getScaleValue(d[0]), + this.yAxis.getScaleValue(d[1]), + ]); + + const barPaddingPercent = 5; + + const barWidth = this.xAxis.getTickInnerPadding() * (1 - barPaddingPercent / 100); + const barWidthHalf = barWidth / 2; + + return [ + { + groupTexts: ['plot', 'bar-plot'], + 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: '#ff0000', + strokeWidth: 0, + strokeFill: '#0000ff', + })), + }, + ]; + } +} diff --git a/packages/mermaid/src/diagrams/xychart/chartBuilder/components/plot/index.ts b/packages/mermaid/src/diagrams/xychart/chartBuilder/components/plot/index.ts index fb91a053a..1c807276e 100644 --- a/packages/mermaid/src/diagrams/xychart/chartBuilder/components/plot/index.ts +++ b/packages/mermaid/src/diagrams/xychart/chartBuilder/components/plot/index.ts @@ -9,9 +9,10 @@ import { ChartPlotEnum, } from '../../Interfaces.js'; import { IAxis } from '../axis/index.js'; -import { ChartComponent } from './../Interfaces.js'; +import { ChartComponent } from '../../Interfaces.js'; import { LinePlot } from './LinePlot.js'; import { PlotBorder } from './PlotBorder.js'; +import { BarPlot } from './BarPlot.js'; export interface IPlot extends ChartComponent { @@ -70,6 +71,11 @@ export class Plot implements IPlot { drawableElem.push(...linePlot.getDrawableElement()) } break; + case ChartPlotEnum.BAR: { + const barPlot = new BarPlot(plot.data, this.boundingRect, this.xAxis, this.yAxis) + drawableElem.push(...barPlot.getDrawableElement()); + } + break; } } return drawableElem; diff --git a/packages/mermaid/src/diagrams/xychart/chartBuilder/index.ts b/packages/mermaid/src/diagrams/xychart/chartBuilder/index.ts index 628965d44..2b7f59211 100644 --- a/packages/mermaid/src/diagrams/xychart/chartBuilder/index.ts +++ b/packages/mermaid/src/diagrams/xychart/chartBuilder/index.ts @@ -67,6 +67,14 @@ export class XYChartBuilder { }, title: 'this is a sample task', plots: [ + { + type: ChartPlotEnum.BAR, + data: [ + ['category1', 23], + ['category2', 56], + ['category3', 34], + ], + }, { type: ChartPlotEnum.LINE, data: [