mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-01-14 06:43:25 +08:00
Fixed some issue related to rendering and space management
This commit is contained in:
parent
553be985ae
commit
355263a4fb
@ -20,8 +20,8 @@
|
|||||||
title Basic xychart
|
title Basic xychart
|
||||||
x-axis "this is x axis" [category1, "category 2", category3, category4]
|
x-axis "this is x axis" [category1, "category 2", category3, category4]
|
||||||
y-axis yaxisText 10 --> 150
|
y-axis yaxisText 10 --> 150
|
||||||
line [23, 46, 75, 43]
|
|
||||||
bar "sample bat" [52, 96, 35, 10]
|
bar "sample bat" [52, 96, 35, 10]
|
||||||
|
line [23, 46, 75, 43]
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
@ -32,11 +32,22 @@
|
|||||||
title Basic xychart
|
title Basic xychart
|
||||||
x-axis "this is x axis" [category1, "category 2", category3, category4]
|
x-axis "this is x axis" [category1, "category 2", category3, category4]
|
||||||
y-axis yaxisText 10 --> 150
|
y-axis yaxisText 10 --> 150
|
||||||
line [23, 46, 75, 43]
|
|
||||||
bar "sample bat" [52, 96, 35, 10]
|
bar "sample bat" [52, 96, 35, 10]
|
||||||
|
line [23, 46, 75, 43]
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
|
<h1>XY Charts demos</h1>
|
||||||
|
<pre class="mermaid">
|
||||||
|
xychart-beta horizontal
|
||||||
|
title Basic xychart
|
||||||
|
x-axis "this is x axis" [category1, "category 2", category3, category4]
|
||||||
|
y-axis yaxisText 10 --> 150
|
||||||
|
line [23, 46, 75, 43]
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import mermaid from './mermaid.esm.mjs';
|
import mermaid from './mermaid.esm.mjs';
|
||||||
mermaid.initialize({
|
mermaid.initialize({
|
||||||
|
@ -26,6 +26,10 @@ export interface BarPlotData {
|
|||||||
|
|
||||||
export type PlotData = LinePlotData | BarPlotData;
|
export type PlotData = LinePlotData | BarPlotData;
|
||||||
|
|
||||||
|
export function isBarPlot(data: PlotData): data is BarPlotData {
|
||||||
|
return data.type === ChartPlotEnum.BAR;
|
||||||
|
}
|
||||||
|
|
||||||
export interface BandAxisDataType {
|
export interface BandAxisDataType {
|
||||||
title: string;
|
title: string;
|
||||||
categories: string[];
|
categories: string[];
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { log } from '../../../logger.js';
|
import { log } from '../../../logger.js';
|
||||||
import { DrawableElem, XYChartData } from './Interfaces.js';
|
import { DrawableElem, XYChartData, isBarPlot } from './Interfaces.js';
|
||||||
import { getChartTitleComponent } from './components/ChartTitle.js';
|
import { getChartTitleComponent } from './components/ChartTitle.js';
|
||||||
import { ChartComponent } from './Interfaces.js';
|
import { ChartComponent } from './Interfaces.js';
|
||||||
import { IAxis, getAxis } from './components/axis/index.js';
|
import { IAxis, getAxis } from './components/axis/index.js';
|
||||||
@ -13,7 +13,7 @@ export class Orchestrator {
|
|||||||
xAxis: IAxis;
|
xAxis: IAxis;
|
||||||
yAxis: IAxis;
|
yAxis: IAxis;
|
||||||
};
|
};
|
||||||
constructor(private chartConfig: XYChartConfig, chartData: XYChartData) {
|
constructor(private chartConfig: XYChartConfig, private chartData: XYChartData) {
|
||||||
this.componentStore = {
|
this.componentStore = {
|
||||||
title: getChartTitleComponent(chartConfig, chartData),
|
title: getChartTitleComponent(chartConfig, chartData),
|
||||||
plot: getPlotComponent(chartConfig, chartData),
|
plot: getPlotComponent(chartConfig, chartData),
|
||||||
@ -87,6 +87,9 @@ export class Orchestrator {
|
|||||||
this.componentStore.xAxis.setBoundingBoxXY({ x: chartX, y: chartY + chartHeight });
|
this.componentStore.xAxis.setBoundingBoxXY({ x: chartX, y: chartY + chartHeight });
|
||||||
this.componentStore.yAxis.setRange([chartY, chartY + chartHeight]);
|
this.componentStore.yAxis.setRange([chartY, chartY + chartHeight]);
|
||||||
this.componentStore.yAxis.setBoundingBoxXY({ x: 0, y: chartY });
|
this.componentStore.yAxis.setBoundingBoxXY({ x: 0, y: chartY });
|
||||||
|
if(this.chartData.plots.find(p => isBarPlot(p))) {
|
||||||
|
this.componentStore.xAxis.recalculateOuterPaddingToDrawBar();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private calculateHorizonatalSpace() {
|
private calculateHorizonatalSpace() {
|
||||||
@ -156,6 +159,9 @@ export class Orchestrator {
|
|||||||
this.componentStore.yAxis.setBoundingBoxXY({ x: chartX, y: titleYEnd });
|
this.componentStore.yAxis.setBoundingBoxXY({ x: chartX, y: titleYEnd });
|
||||||
this.componentStore.xAxis.setRange([chartY, chartY + chartHeight]);
|
this.componentStore.xAxis.setRange([chartY, chartY + chartHeight]);
|
||||||
this.componentStore.xAxis.setBoundingBoxXY({ x: 0, y: chartY });
|
this.componentStore.xAxis.setBoundingBoxXY({ x: 0, y: chartY });
|
||||||
|
if(this.chartData.plots.find(p => isBarPlot(p))) {
|
||||||
|
this.componentStore.xAxis.recalculateOuterPaddingToDrawBar();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private calculateSpace() {
|
private calculateSpace() {
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
import { ScaleBand, scaleBand } from 'd3';
|
import { ScaleBand, scaleBand } from 'd3';
|
||||||
import { AxisConfig } from '../../Interfaces.js';
|
import { XYChartAxisConfig } from '../../../../../config.type.js';
|
||||||
|
import { log } from '../../../../../logger.js';
|
||||||
import { ITextDimensionCalculator } from '../../TextDimensionCalculator.js';
|
import { ITextDimensionCalculator } from '../../TextDimensionCalculator.js';
|
||||||
import { BaseAxis } from './BaseAxis.js';
|
import { BaseAxis } from './BaseAxis.js';
|
||||||
import { log } from '../../../../../logger.js';
|
|
||||||
|
|
||||||
export class BandAxis extends BaseAxis {
|
export class BandAxis extends BaseAxis {
|
||||||
private scale: ScaleBand<string>;
|
private scale: ScaleBand<string>;
|
||||||
private categories: string[];
|
private categories: string[];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
axisConfig: AxisConfig,
|
axisConfig: XYChartAxisConfig,
|
||||||
categories: string[],
|
categories: string[],
|
||||||
title: string,
|
title: string,
|
||||||
textDimensionCalculator: ITextDimensionCalculator
|
textDimensionCalculator: ITextDimensionCalculator
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { Dimension, Point, DrawableElem, BoundingRect, AxisConfig } from '../../Interfaces.js';
|
import { XYChartAxisConfig } from '../../../../../config.type.js';
|
||||||
import { AxisPosition, IAxis } from './index.js';
|
|
||||||
import { ITextDimensionCalculator } from '../../TextDimensionCalculator.js';
|
|
||||||
import { log } from '../../../../../logger.js';
|
import { log } from '../../../../../logger.js';
|
||||||
|
import { BoundingRect, Dimension, DrawableElem, Point } from '../../Interfaces.js';
|
||||||
|
import { ITextDimensionCalculator } from '../../TextDimensionCalculator.js';
|
||||||
|
import { AxisPosition, IAxis } from './index.js';
|
||||||
|
|
||||||
export abstract class BaseAxis implements IAxis {
|
export abstract class BaseAxis implements IAxis {
|
||||||
protected boundingRect: BoundingRect = { x: 0, y: 0, width: 0, height: 0 };
|
protected boundingRect: BoundingRect = { x: 0, y: 0, width: 0, height: 0 };
|
||||||
@ -10,10 +11,10 @@ export abstract class BaseAxis implements IAxis {
|
|||||||
protected showTitle = false;
|
protected showTitle = false;
|
||||||
protected showLabel = false;
|
protected showLabel = false;
|
||||||
protected showTick = false;
|
protected showTick = false;
|
||||||
protected innerPadding = 0;
|
protected outerPadding = 0;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected axisConfig: AxisConfig,
|
protected axisConfig: XYChartAxisConfig,
|
||||||
protected title: string,
|
protected title: string,
|
||||||
protected textDimensionCalculator: ITextDimensionCalculator
|
protected textDimensionCalculator: ITextDimensionCalculator
|
||||||
) {
|
) {
|
||||||
@ -28,7 +29,7 @@ export abstract class BaseAxis implements IAxis {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getRange(): [number, number] {
|
getRange(): [number, number] {
|
||||||
return [this.range[0] + this.innerPadding, this.range[1] - this.innerPadding];
|
return [this.range[0] + this.outerPadding, this.range[1] - this.outerPadding];
|
||||||
}
|
}
|
||||||
|
|
||||||
setAxisPosition(axisPosition: AxisPosition): void {
|
setAxisPosition(axisPosition: AxisPosition): void {
|
||||||
@ -45,9 +46,8 @@ export abstract class BaseAxis implements IAxis {
|
|||||||
return Math.abs(this.range[0] - this.range[1]) / this.getTickValues().length;
|
return Math.abs(this.range[0] - this.range[1]) / this.getTickValues().length;
|
||||||
}
|
}
|
||||||
|
|
||||||
getTickInnerPadding(): number {
|
getAxisOuterPadding(): number {
|
||||||
return this.innerPadding * 2;
|
return this.outerPadding;
|
||||||
// return Math.abs(this.range[0] - this.range[1]) / this.getTickValues().length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private getLabelDimension(): Dimension {
|
private getLabelDimension(): Dimension {
|
||||||
@ -57,11 +57,18 @@ export abstract class BaseAxis implements IAxis {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
recalculateOuterPaddingToDrawBar(): void {
|
||||||
|
if((0.7 * this.getTickDistance()) > (this.outerPadding * 2) ) {
|
||||||
|
this.outerPadding = Math.floor((0.7 * this.getTickDistance())/2);
|
||||||
|
}
|
||||||
|
this.recalculateScale();
|
||||||
|
}
|
||||||
|
|
||||||
private calculateSpaceIfDrawnHorizontally(availableSpace: Dimension) {
|
private calculateSpaceIfDrawnHorizontally(availableSpace: Dimension) {
|
||||||
let availableHeight = availableSpace.height;
|
let availableHeight = availableSpace.height;
|
||||||
if (this.axisConfig.showLabel) {
|
if (this.axisConfig.showLabel) {
|
||||||
const spaceRequired = this.getLabelDimension();
|
const spaceRequired = this.getLabelDimension();
|
||||||
this.innerPadding = spaceRequired.width / 2;
|
this.outerPadding = spaceRequired.width / 2;
|
||||||
const heightRequired = spaceRequired.height + this.axisConfig.lablePadding * 2;
|
const heightRequired = spaceRequired.height + this.axisConfig.lablePadding * 2;
|
||||||
log.trace('height required for axis label: ', heightRequired);
|
log.trace('height required for axis label: ', heightRequired);
|
||||||
if (heightRequired <= availableHeight) {
|
if (heightRequired <= availableHeight) {
|
||||||
@ -93,7 +100,7 @@ export abstract class BaseAxis implements IAxis {
|
|||||||
let availableWidth = availableSpace.width;
|
let availableWidth = availableSpace.width;
|
||||||
if (this.axisConfig.showLabel) {
|
if (this.axisConfig.showLabel) {
|
||||||
const spaceRequired = this.getLabelDimension();
|
const spaceRequired = this.getLabelDimension();
|
||||||
this.innerPadding = spaceRequired.height / 2;
|
this.outerPadding = spaceRequired.height / 2;
|
||||||
const widthRequired = spaceRequired.width + this.axisConfig.lablePadding * 2;
|
const widthRequired = spaceRequired.width + this.axisConfig.lablePadding * 2;
|
||||||
log.trace('width required for axis label: ', widthRequired);
|
log.trace('width required for axis label: ', widthRequired);
|
||||||
if (widthRequired <= availableWidth) {
|
if (widthRequired <= availableWidth) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { ScaleLinear, scaleLinear } from 'd3';
|
import { ScaleLinear, scaleLinear } from 'd3';
|
||||||
|
import { XYChartAxisConfig } from '../../../../../config.type.js';
|
||||||
import { log } from '../../../../../logger.js';
|
import { log } from '../../../../../logger.js';
|
||||||
import { AxisConfig } from '../../Interfaces.js';
|
|
||||||
import { ITextDimensionCalculator } from '../../TextDimensionCalculator.js';
|
import { ITextDimensionCalculator } from '../../TextDimensionCalculator.js';
|
||||||
import { BaseAxis } from './BaseAxis.js';
|
import { BaseAxis } from './BaseAxis.js';
|
||||||
|
|
||||||
@ -9,7 +9,7 @@ export class LinearAxis extends BaseAxis {
|
|||||||
private domain: [number, number];
|
private domain: [number, number];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
axisConfig: AxisConfig,
|
axisConfig: XYChartAxisConfig,
|
||||||
domain: [number, number],
|
domain: [number, number],
|
||||||
title: string,
|
title: string,
|
||||||
textDimensionCalculator: ITextDimensionCalculator
|
textDimensionCalculator: ITextDimensionCalculator
|
||||||
|
@ -13,8 +13,9 @@ export type AxisPosition = 'left' | 'right' | '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;
|
getAxisOuterPadding(): number;
|
||||||
getTickDistance(): number;
|
getTickDistance(): number;
|
||||||
|
recalculateOuterPaddingToDrawBar(): void;
|
||||||
setRange(range: [number, number]): void;
|
setRange(range: [number, number]): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ export class BarPlot {
|
|||||||
const barPaddingPercent = 5;
|
const barPaddingPercent = 5;
|
||||||
|
|
||||||
const barWidth =
|
const barWidth =
|
||||||
Math.min(this.xAxis.getTickInnerPadding(), this.xAxis.getTickDistance()) *
|
Math.min(this.xAxis.getAxisOuterPadding() * 2, this.xAxis.getTickDistance()) *
|
||||||
(1 - barPaddingPercent / 100);
|
(1 - barPaddingPercent / 100);
|
||||||
const barWidthHalf = barWidth / 2;
|
const barWidthHalf = barWidth / 2;
|
||||||
|
|
||||||
|
@ -125,8 +125,9 @@ function setYAxisRangeData(min: number, max: number) {
|
|||||||
function setLineData(title: string, data: number[]) {
|
function setLineData(title: string, data: number[]) {
|
||||||
if (isBandAxisData(xyChartData.xAxis)) {
|
if (isBandAxisData(xyChartData.xAxis)) {
|
||||||
xyChartData.plots.push({
|
xyChartData.plots.push({
|
||||||
type: ChartPlotEnum.BAR,
|
type: ChartPlotEnum.LINE,
|
||||||
fill: '#0000bb',
|
strokeFill: '#00ff00',
|
||||||
|
strokeWidth: 2,
|
||||||
data: xyChartData.xAxis.categories.map((c, i) => [c, data[i]]),
|
data: xyChartData.xAxis.categories.map((c, i) => [c, data[i]]),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -134,9 +135,8 @@ function setLineData(title: string, data: number[]) {
|
|||||||
function setBarData(title: string, data: number[]) {
|
function setBarData(title: string, data: number[]) {
|
||||||
if (isBandAxisData(xyChartData.xAxis)) {
|
if (isBandAxisData(xyChartData.xAxis)) {
|
||||||
xyChartData.plots.push({
|
xyChartData.plots.push({
|
||||||
type: ChartPlotEnum.LINE,
|
type: ChartPlotEnum.BAR,
|
||||||
strokeFill: '#00ff00',
|
fill: '#0000bb',
|
||||||
strokeWidth: 2,
|
|
||||||
data: xyChartData.xAxis.categories.map((c, i) => [c, data[i]]),
|
data: xyChartData.xAxis.categories.map((c, i) => [c, data[i]]),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user