mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-09-11 19:39:43 +02:00
Added support for bar plot
This commit is contained in:
@@ -1,19 +1,12 @@
|
|||||||
export enum ChartPlotEnum {
|
export enum ChartPlotEnum {
|
||||||
LINE = 'line',
|
LINE = 'line',
|
||||||
|
BAR = 'bar',
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum ChartLayoutElem {
|
export interface ChartComponent {
|
||||||
NULL = 'null',
|
calculateSpace(availableSpace: Dimension): Dimension;
|
||||||
CHART = 'chart',
|
setBoundingBoxXY(point: Point): void;
|
||||||
TITLE = 'title',
|
getDrawableElements(): DrawableElem[];
|
||||||
XAXISLABEL = 'xaxislabel',
|
|
||||||
XAXISTITLE = 'xaxistitle',
|
|
||||||
YAXISLABEL = 'yaxislabel',
|
|
||||||
YAXISTITLE = 'yaxistitle',
|
|
||||||
}
|
|
||||||
export enum XYChartYAxisPosition {
|
|
||||||
LEFT = 'left',
|
|
||||||
RIGHT = 'right',
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum OrientationEnum {
|
export enum OrientationEnum {
|
||||||
@@ -21,16 +14,6 @@ export enum OrientationEnum {
|
|||||||
HORIZONTAL = 'horizontal',
|
HORIZONTAL = 'horizontal',
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ChartLayout = ChartLayoutElem[][];
|
|
||||||
|
|
||||||
export type VisibilityOption = {
|
|
||||||
chartTitle: boolean;
|
|
||||||
xAxisTitle: boolean;
|
|
||||||
xAxisLabel: boolean;
|
|
||||||
yAxisTitle: boolean;
|
|
||||||
yAxisLabel: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface AxisConfig {
|
export interface AxisConfig {
|
||||||
showLabel: boolean;
|
showLabel: boolean;
|
||||||
labelFontSize: number;
|
labelFontSize: number;
|
||||||
@@ -64,7 +47,7 @@ export interface XYChartConfig {
|
|||||||
export type SimplePlotDataType = [string | number, number][];
|
export type SimplePlotDataType = [string | number, number][];
|
||||||
|
|
||||||
export interface LinePlotData {
|
export interface LinePlotData {
|
||||||
type: ChartPlotEnum.LINE;
|
type: ChartPlotEnum.LINE | ChartPlotEnum.BAR;
|
||||||
data: SimplePlotDataType;
|
data: SimplePlotDataType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import { log } from '../../../logger.js';
|
import { log } from '../../../logger.js';
|
||||||
import { DrawableElem, XYChartConfig, XYChartData } from './Interfaces.js';
|
import { DrawableElem, XYChartConfig, XYChartData } from './Interfaces.js';
|
||||||
import { getChartTitleComponent } from './components/ChartTitle.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 { IAxis, getAxis } from './components/axis/index.js';
|
||||||
import { IPlot, getPlotComponent } from './components/plot/index.js';
|
import { IPlot, getPlotComponent } from './components/plot/index.js';
|
||||||
|
|
||||||
|
@@ -8,7 +8,7 @@ import {
|
|||||||
Point,
|
Point,
|
||||||
OrientationEnum,
|
OrientationEnum,
|
||||||
} from '../Interfaces.js';
|
} from '../Interfaces.js';
|
||||||
import { ChartComponent } from './Interfaces.js';
|
import { ChartComponent } from '../Interfaces.js';
|
||||||
|
|
||||||
export class ChartTitle implements ChartComponent {
|
export class ChartTitle implements ChartComponent {
|
||||||
private boundingRect: BoundingRect;
|
private boundingRect: BoundingRect;
|
||||||
|
@@ -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[];
|
|
||||||
}
|
|
@@ -41,6 +41,11 @@ export abstract class BaseAxis implements IAxis {
|
|||||||
|
|
||||||
abstract getTickValues(): Array<string | number>;
|
abstract getTickValues(): Array<string | number>;
|
||||||
|
|
||||||
|
getTickInnerPadding(): number {
|
||||||
|
return this.innerPadding * 2;
|
||||||
|
// return Math.abs(this.range[0] - this.range[1]) / this.getTickValues().length;
|
||||||
|
}
|
||||||
|
|
||||||
private getLabelDimension(): Dimension {
|
private getLabelDimension(): Dimension {
|
||||||
return this.textDimensionCalculator.getDimension(
|
return this.textDimensionCalculator.getDimension(
|
||||||
this.getTickValues().map((tick) => tick.toString()),
|
this.getTickValues().map((tick) => tick.toString()),
|
||||||
@@ -162,7 +167,9 @@ export abstract class BaseAxis implements IAxis {
|
|||||||
type: 'path',
|
type: 'path',
|
||||||
groupTexts: ['left-axis', 'ticks'],
|
groupTexts: ['left-axis', 'ticks'],
|
||||||
data: this.getTickValues().map((tick) => ({
|
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,
|
strokeFill: this.axisConfig.tickFill,
|
||||||
strokeWidth: this.axisConfig.tickWidth,
|
strokeWidth: this.axisConfig.tickWidth,
|
||||||
})),
|
})),
|
||||||
@@ -212,7 +219,9 @@ export abstract class BaseAxis implements IAxis {
|
|||||||
type: 'path',
|
type: 'path',
|
||||||
groupTexts: ['bottom-axis', 'ticks'],
|
groupTexts: ['bottom-axis', 'ticks'],
|
||||||
data: this.getTickValues().map((tick) => ({
|
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,
|
strokeFill: this.axisConfig.tickFill,
|
||||||
strokeWidth: this.axisConfig.tickWidth,
|
strokeWidth: this.axisConfig.tickWidth,
|
||||||
})),
|
})),
|
||||||
|
@@ -5,15 +5,16 @@ import {
|
|||||||
LinearAxisDataType
|
LinearAxisDataType
|
||||||
} from '../../Interfaces.js';
|
} from '../../Interfaces.js';
|
||||||
import { TextDimensionCalculator } from '../../TextDimensionCalculator.js';
|
import { TextDimensionCalculator } from '../../TextDimensionCalculator.js';
|
||||||
import { ChartComponent } from '../Interfaces.js';
|
import { ChartComponent } from '../../Interfaces.js';
|
||||||
import { BandAxis } from './BandAxis.js';
|
import { BandAxis } from './BandAxis.js';
|
||||||
import { LinearAxis } from './LinearAxis.js';
|
import { LinearAxis } from './LinearAxis.js';
|
||||||
|
|
||||||
export type AxisPosition = 'left' | 'bottom';
|
export type AxisPosition = 'left' | 'bottom' | 'top' | 'bottom';
|
||||||
|
|
||||||
export interface IAxis extends ChartComponent {
|
export interface IAxis extends ChartComponent {
|
||||||
getScaleValue(value: string | number): number;
|
getScaleValue(value: string | number): number;
|
||||||
setAxisPosition(axisPosition: AxisPosition): void;
|
setAxisPosition(axisPosition: AxisPosition): void;
|
||||||
|
getTickInnerPadding(): number;
|
||||||
setRange(range: [number, number]): void;
|
setRange(range: [number, number]): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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',
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@@ -9,9 +9,10 @@ import {
|
|||||||
ChartPlotEnum,
|
ChartPlotEnum,
|
||||||
} from '../../Interfaces.js';
|
} from '../../Interfaces.js';
|
||||||
import { IAxis } from '../axis/index.js';
|
import { IAxis } from '../axis/index.js';
|
||||||
import { ChartComponent } from './../Interfaces.js';
|
import { ChartComponent } from '../../Interfaces.js';
|
||||||
import { LinePlot } from './LinePlot.js';
|
import { LinePlot } from './LinePlot.js';
|
||||||
import { PlotBorder } from './PlotBorder.js';
|
import { PlotBorder } from './PlotBorder.js';
|
||||||
|
import { BarPlot } from './BarPlot.js';
|
||||||
|
|
||||||
|
|
||||||
export interface IPlot extends ChartComponent {
|
export interface IPlot extends ChartComponent {
|
||||||
@@ -70,6 +71,11 @@ export class Plot implements IPlot {
|
|||||||
drawableElem.push(...linePlot.getDrawableElement())
|
drawableElem.push(...linePlot.getDrawableElement())
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case ChartPlotEnum.BAR: {
|
||||||
|
const barPlot = new BarPlot(plot.data, this.boundingRect, this.xAxis, this.yAxis)
|
||||||
|
drawableElem.push(...barPlot.getDrawableElement());
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return drawableElem;
|
return drawableElem;
|
||||||
|
@@ -67,6 +67,14 @@ export class XYChartBuilder {
|
|||||||
},
|
},
|
||||||
title: 'this is a sample task',
|
title: 'this is a sample task',
|
||||||
plots: [
|
plots: [
|
||||||
|
{
|
||||||
|
type: ChartPlotEnum.BAR,
|
||||||
|
data: [
|
||||||
|
['category1', 23],
|
||||||
|
['category2', 56],
|
||||||
|
['category3', 34],
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
type: ChartPlotEnum.LINE,
|
type: ChartPlotEnum.LINE,
|
||||||
data: [
|
data: [
|
||||||
|
Reference in New Issue
Block a user