mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-01-28 07:03:17 +08:00
Added support for bar plot
This commit is contained in:
parent
cc1d6af232
commit
547a22edef
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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>;
|
||||
|
||||
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,
|
||||
})),
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
} 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;
|
||||
|
@ -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: [
|
||||
|
Loading…
x
Reference in New Issue
Block a user