Rendered axis with basic line chart

This commit is contained in:
Subhash Halder 2023-06-10 17:02:55 +05:30
parent 93697b74f4
commit 183bc0a978
11 changed files with 398 additions and 176 deletions

View File

@ -31,6 +31,17 @@ export type VisibilityOption = {
yAxisLabel: boolean; yAxisLabel: boolean;
}; };
export interface AxisConfig {
showLabel: boolean;
labelFontSize: number;
lablePadding: number;
labelColor: string;
showTitle: boolean;
titleFontSize: number;
titlePadding: number;
titleColor: string;
}
export interface XYChartConfig { export interface XYChartConfig {
width: number; width: number;
height: number; height: number;
@ -38,16 +49,9 @@ export interface XYChartConfig {
titleFontSize: number; titleFontSize: number;
titleFill: string; titleFill: string;
titlePadding: number; titlePadding: number;
xAxisFontSize: number; showtitle: boolean;
xAxisTitleFontSize: number; xAxis: AxisConfig;
yAxisFontSize: number; yAxis: AxisConfig;
yAxisTitleFontSize: number;
yAxisPosition: XYChartYAxisPosition;
showChartTitle: boolean;
showXAxisLable: boolean;
showXAxisTitle: boolean;
showYAxisLabel: boolean;
showYAxisTitle: boolean;
chartOrientation: OrientationEnum; chartOrientation: OrientationEnum;
plotReservedSpacePercent: number; plotReservedSpacePercent: number;
} }

View File

@ -1,22 +1,23 @@
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 './components/Interfaces.js';
import { IAxis, getAxis } from './components/axis/index.js'; import { IAxis, getAxis } from './components/axis/index.js';
import { IPlot, getPlotComponent, isTypeIPlot } from './components/plot/index.js'; import { IPlot, getPlotComponent } from './components/plot/index.js';
export class Orchestrator { export class Orchestrator {
private componentStore: { private componentStore: {
title: ChartComponent, title: ChartComponent;
plot: IPlot, plot: IPlot;
xAxis: IAxis, xAxis: IAxis;
yAxis: IAxis, yAxis: IAxis;
}; };
constructor(private chartConfig: XYChartConfig, chartData: XYChartData) { constructor(private chartConfig: XYChartConfig, chartData: XYChartData) {
this.componentStore = { this.componentStore = {
title: getChartTitleComponent(chartConfig, chartData), title: getChartTitleComponent(chartConfig, chartData),
plot: getPlotComponent(chartConfig, chartData), plot: getPlotComponent(chartConfig, chartData),
xAxis: getAxis(chartData.xAxis, chartConfig), xAxis: getAxis(chartData.xAxis, chartConfig.xAxis),
yAxis: getAxis(chartData.yAxis, chartConfig), yAxis: getAxis(chartData.yAxis, chartConfig.yAxis),
}; };
} }
@ -25,9 +26,10 @@ export class Orchestrator {
let availableHeight = this.chartConfig.height; let availableHeight = this.chartConfig.height;
let chartX = 0; let chartX = 0;
let chartY = 0; let chartY = 0;
const chartWidth = Math.floor((availableWidth * this.chartConfig.plotReservedSpacePercent) / 100); let chartWidth = Math.floor((availableWidth * this.chartConfig.plotReservedSpacePercent) / 100);
const chartHeight = Math.floor((availableHeight * this.chartConfig.plotReservedSpacePercent) / 100); let chartHeight = Math.floor(
(availableHeight * this.chartConfig.plotReservedSpacePercent) / 100
);
let spaceUsed = this.componentStore.plot.calculateSpace({ let spaceUsed = this.componentStore.plot.calculateSpace({
width: chartWidth, width: chartWidth,
height: chartHeight, height: chartHeight,
@ -39,19 +41,42 @@ export class Orchestrator {
width: this.chartConfig.width, width: this.chartConfig.width,
height: availableHeight, height: availableHeight,
}); });
log.trace('space used by title: ', spaceUsed);
chartY = spaceUsed.height; chartY = spaceUsed.height;
availableWidth -= spaceUsed.width;
availableHeight -= spaceUsed.height; availableHeight -= spaceUsed.height;
// this.componentStore.xAxis.setAxisPosition('bottom');
// spaceUsed = this.componentStore.xAxis.calculateSpace({ spaceUsed = this.componentStore.xAxis.calculateSpace({
// width: availableWidth, width: availableWidth,
// height: availableHeight, height: availableHeight,
// }); });
// availableWidth -= spaceUsed.width; log.trace('space used by xaxis: ', spaceUsed);
// availableHeight -= spaceUsed.height; availableHeight -= spaceUsed.height;
this.componentStore.plot.setBoundingBoxXY({x: chartX, y: chartY}); this.componentStore.yAxis.setAxisPosition('left');
spaceUsed = this.componentStore.yAxis.calculateSpace({
width: availableWidth,
height: availableHeight,
});
log.trace('space used by yaxis: ', spaceUsed);
chartX = spaceUsed.width;
availableWidth -= spaceUsed.width;
if (availableWidth > 0) {
chartWidth += availableWidth;
availableWidth = 0;
}
if (availableHeight > 0) {
chartHeight += availableHeight;
availableHeight = 0;
}
log.trace(
`Final chart dimansion: x = ${chartX}, y = ${chartY}, width = ${chartWidth}, height = ${chartHeight}`
);
this.componentStore.plot.setBoundingBoxXY({ x: chartX, y: chartY });
this.componentStore.xAxis.setRange([chartX, chartX + chartWidth]); this.componentStore.xAxis.setRange([chartX, chartX + chartWidth]);
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 });
} }
getDrawableElement() { getDrawableElement() {

View File

@ -1,15 +1,15 @@
import { Dimension } from './Interfaces.js'; import { Dimension } from './Interfaces.js';
export interface ITextDimensionCalculator { export interface ITextDimensionCalculator {
getDimension(text: string): Dimension; getDimension(texts: string[], fontSize: number, fontFamily?: string ): Dimension;
} }
export class TextDimensionCalculator implements ITextDimensionCalculator { export class TextDimensionCalculator implements ITextDimensionCalculator {
constructor(private fontSize: number, private fontFamily: string) {} constructor() {}
getDimension(text: string): Dimension { getDimension(texts: string[], fontSize: number): Dimension {
return { return {
width: text.length * this.fontSize, width: texts.reduce((acc, cur) => Math.max(cur.length, acc), 0) * fontSize,
height: this.fontSize, height: fontSize,
}; };
} }
} }

View File

@ -25,7 +25,7 @@ export class ChartTitle implements ChartComponent {
width: 0, width: 0,
height: 0, height: 0,
}; };
this.showChartTitle = !!(this.chartData.title && this.chartConfig.showChartTitle); this.showChartTitle = !!(this.chartData.title && this.chartConfig.showtitle);
this.orientation = OrientationEnum.VERTICAL; this.orientation = OrientationEnum.VERTICAL;
} }
setOrientation(orientation: OrientationEnum): void { setOrientation(orientation: OrientationEnum): void {
@ -36,7 +36,7 @@ export class ChartTitle implements ChartComponent {
this.boundingRect.y = point.y; this.boundingRect.y = point.y;
} }
calculateSpace(availableSpace: Dimension): Dimension { calculateSpace(availableSpace: Dimension): Dimension {
const titleDimension = this.textDimensionCalculator.getDimension(this.chartData.title); const titleDimension = this.textDimensionCalculator.getDimension([this.chartData.title], this.chartConfig.titleFontSize);
const widthRequired = Math.max(titleDimension.width, availableSpace.width); const widthRequired = Math.max(titleDimension.width, availableSpace.width);
const heightRequired = titleDimension.height + 2 * this.chartConfig.titlePadding; const heightRequired = titleDimension.height + 2 * this.chartConfig.titlePadding;
if ( if (
@ -81,9 +81,6 @@ export function getChartTitleComponent(
chartConfig: XYChartConfig, chartConfig: XYChartConfig,
chartData: XYChartData chartData: XYChartData
): ChartComponent { ): ChartComponent {
const textDimensionCalculator = new TextDimensionCalculator( const textDimensionCalculator = new TextDimensionCalculator();
chartConfig.titleFontSize,
chartConfig.fontFamily
);
return new ChartTitle(textDimensionCalculator, chartConfig, chartData); return new ChartTitle(textDimensionCalculator, chartConfig, chartData);
} }

View File

@ -1,7 +1,6 @@
import { Dimension, DrawableElem, OrientationEnum, Point } from '../Interfaces.js'; import { Dimension, DrawableElem, OrientationEnum, Point } from '../Interfaces.js';
export interface ChartComponent { export interface ChartComponent {
setOrientation(orientation: OrientationEnum): void;
calculateSpace(availableSpace: Dimension): Dimension; calculateSpace(availableSpace: Dimension): Dimension;
setBoundingBoxXY(point: Point): void; setBoundingBoxXY(point: Point): void;
getDrawableElements(): DrawableElem[]; getDrawableElements(): DrawableElem[];

View File

@ -1,54 +1,43 @@
import { ScaleBand, scaleBand } from 'd3'; import { ScaleBand, scaleBand } from 'd3';
import { import { AxisConfig } from '../../Interfaces.js';
Dimension, import { ITextDimensionCalculator } from '../../TextDimensionCalculator.js';
Point, import { BaseAxis } from './BaseAxis.js';
DrawableElem, import { log } from '../../../../../logger.js';
BoundingRect,
OrientationEnum,
XYChartConfig,
} from '../../Interfaces.js';
import { IAxis } from './index.js';
export class BandAxis implements IAxis { export class BandAxis extends BaseAxis {
private scale: ScaleBand<string>; private scale: ScaleBand<string>;
private range: [number, number];
private boundingRect: BoundingRect;
private orientation: OrientationEnum;
private categories: string[]; private categories: string[];
constructor(private chartConfig: XYChartConfig, categories: string[]) { constructor(
this.range = [0, 10]; axisConfig: AxisConfig,
categories: string[],
title: string,
textDimensionCalculator: ITextDimensionCalculator
) {
super(axisConfig, title, textDimensionCalculator);
this.categories = categories; this.categories = categories;
this.scale = scaleBand().domain(this.categories).range(this.range); this.scale = scaleBand().domain(this.categories).range(this.getRange());
this.boundingRect = { x: 0, y: 0, width: 0, height: 0 };
this.orientation = OrientationEnum.VERTICAL;
} }
setRange(range: [number, number]): void { setRange(range: [number, number]): void {
this.range = range; super.setRange(range);
this.scale = scaleBand().domain(this.categories).range(this.range);
} }
setOrientation(orientation: OrientationEnum): void {
this.orientation = orientation; recalculateScale(): void {
this.scale = scaleBand()
.domain(this.categories)
.range(this.getRange())
.paddingInner(1)
.paddingOuter(0)
.align(0.5);
log.trace('BandAxis axis final categories, range: ', this.categories, this.getRange());
}
getTickValues(): (string | number)[] {
return this.categories;
} }
getScaleValue(value: string): number { getScaleValue(value: string): number {
return this.scale(value) || this.range[0]; return this.scale(value) || this.getRange()[0];
}
calculateSpace(availableSpace: Dimension): Dimension {
return {
width: availableSpace.width,
height: availableSpace.height,
};
}
setBoundingBoxXY(point: Point): void {
this.boundingRect.x = point.x;
this.boundingRect.y = point.y;
}
getDrawableElements(): DrawableElem[] {
return [];
} }
} }

View File

@ -0,0 +1,217 @@
import {
Dimension,
Point,
DrawableElem,
BoundingRect,
AxisConfig,
} from '../../Interfaces.js';
import { AxisPosition, IAxis } from './index.js';
import { ITextDimensionCalculator } from '../../TextDimensionCalculator.js';
import { log } from '../../../../../logger.js';
export abstract class BaseAxis implements IAxis {
protected boundingRect: BoundingRect = {x: 0, y: 0, width: 0, height: 0};
protected axisPosition: AxisPosition = 'left';
private range: [number, number];
protected showTitle = false;
protected showLabel = false;
protected innerPadding = 0;
constructor(
protected axisConfig: AxisConfig,
protected title: string,
protected textDimensionCalculator: ITextDimensionCalculator
) {
this.range = [0, 10];
this.boundingRect = { x: 0, y: 0, width: 0, height: 0 };
this.axisPosition = 'left';
}
setRange(range: [number, number]): void {
this.range = range;
this.recalculateScale();
}
getRange(): [number, number] {
return [this.range[0] + this.innerPadding, this.range[1] - this.innerPadding];
}
setAxisPosition(axisPosition: AxisPosition): void {
this.axisPosition = axisPosition;
}
abstract getScaleValue(value: number | string): number;
abstract recalculateScale(): void;
abstract getTickValues(): Array<string | number>;
private getLabelDimension(): Dimension {
return this.textDimensionCalculator.getDimension(
this.getTickValues().map((tick) => tick.toString()),
this.axisConfig.labelFontSize
);
}
private calculateSpaceIfDrawnVertical(availableSpace: Dimension) {
let availableHeight = availableSpace.height;
if (this.axisConfig.showLabel) {
const spaceRequired = this.getLabelDimension();
this.innerPadding = spaceRequired.width / 2;
const heightRequired = spaceRequired.height + this.axisConfig.lablePadding * 2;
log.trace('height required for axis label: ', heightRequired);
if (heightRequired <= availableHeight) {
availableHeight -= heightRequired;
this.showLabel = true;
}
}
if (this.axisConfig.showTitle) {
const spaceRequired = this.textDimensionCalculator.getDimension(
[this.title],
this.axisConfig.labelFontSize
);
const heightRequired = spaceRequired.height + this.axisConfig.titlePadding * 2;
log.trace('height required for axis title: ', heightRequired);
if (heightRequired <= availableHeight) {
availableHeight -= heightRequired;
this.showTitle = true;
}
}
this.boundingRect.width = availableSpace.width;
this.boundingRect.height = availableSpace.height - availableHeight;
}
private calculateSpaceIfDrawnHorizontally(availableSpace: Dimension) {
let availableWidth = availableSpace.width;
if (this.axisConfig.showLabel) {
const spaceRequired = this.getLabelDimension();
this.innerPadding = spaceRequired.width / 2;
const widthRequired = spaceRequired.width + this.axisConfig.lablePadding * 2;
log.trace('width required for axis label: ', widthRequired);
if (widthRequired <= availableWidth) {
availableWidth -= widthRequired;
this.showLabel = true;
}
}
if (this.axisConfig.showTitle) {
const spaceRequired = this.textDimensionCalculator.getDimension(
[this.title],
this.axisConfig.labelFontSize
);
const widthRequired = spaceRequired.height + this.axisConfig.lablePadding * 2;
log.trace('width required for axis title: ', widthRequired);
if (widthRequired <= availableWidth) {
availableWidth -= widthRequired;
this.showTitle = true;
}
}
this.boundingRect.width = availableSpace.width - availableWidth;
this.boundingRect.height = availableSpace.height;
}
calculateSpace(availableSpace: Dimension): Dimension {
if (!(this.axisConfig.showLabel || this.axisConfig.showTitle)) {
this.recalculateScale();
return { width: 0, height: 0 };
}
if (this.axisPosition === 'left') {
this.calculateSpaceIfDrawnHorizontally(availableSpace);
} else {
this.calculateSpaceIfDrawnVertical(availableSpace);
}
this.recalculateScale();
return {
width: this.boundingRect.width,
height: this.boundingRect.height,
};
}
setBoundingBoxXY(point: Point): void {
this.boundingRect.x = point.x;
this.boundingRect.y = point.y;
}
private getDrawaableElementsForLeftAxis(): DrawableElem[] {
const drawableElement: DrawableElem[] = [];
if (this.showLabel) {
drawableElement.push({
type: 'text',
groupText: 'left-axis-label',
data: this.getTickValues().map((tick) => ({
text: tick.toString(),
x: this.boundingRect.x + this.boundingRect.width - this.axisConfig.lablePadding,
y: this.getScaleValue(tick),
fill: this.axisConfig.labelColor,
fontSize: this.axisConfig.labelFontSize,
rotation: 0,
verticalPos: 'right',
horizontalPos: 'middle',
})),
});
}
if (this.showTitle) {
drawableElement.push({
type: 'text',
groupText: 'right-axis-label',
data: [{
text: this.title,
x: this.boundingRect.x + this.axisConfig.titlePadding,
y: this.range[0] + (this.range[1] - this.range[0])/2,
fill: this.axisConfig.titleColor,
fontSize: this.axisConfig.titleFontSize,
rotation: 270,
verticalPos: 'center',
horizontalPos: 'top',
}]
})
}
return drawableElement;
}
private getDrawaableElementsForBottomAxis(): DrawableElem[] {
const drawableElement: DrawableElem[] = [];
if (this.showLabel) {
drawableElement.push({
type: 'text',
groupText: 'right-axis-lable',
data: this.getTickValues().map((tick) => ({
text: tick.toString(),
x: this.getScaleValue(tick),
y: this.boundingRect.y + this.axisConfig.lablePadding,
fill: this.axisConfig.labelColor,
fontSize: this.axisConfig.labelFontSize,
rotation: 0,
verticalPos: 'center',
horizontalPos: 'top',
})),
});
}
if (this.showTitle) {
drawableElement.push({
type: 'text',
groupText: 'right-axis-label',
data: [{
text: this.title,
x: this.range[0] + (this.range[1] - this.range[0])/2,
y: this.boundingRect.y + this.boundingRect.height - this.axisConfig.titlePadding,
fill: this.axisConfig.titleColor,
fontSize: this.axisConfig.titleFontSize,
rotation: 0,
verticalPos: 'center',
horizontalPos: 'bottom',
}]
})
}
return drawableElement;
}
getDrawableElements(): DrawableElem[] {
if (this.axisPosition === 'left') {
return this.getDrawaableElementsForLeftAxis();
}
if (this.axisPosition === 'bottom') {
return this.getDrawaableElementsForBottomAxis();
}
return [];
}
}

View File

@ -1,55 +1,37 @@
import { scaleLinear, ScaleLinear } from 'd3'; import { ScaleLinear, scaleLinear } from 'd3';
import { import { AxisConfig, Dimension } from '../../Interfaces.js';
Dimension, import { ITextDimensionCalculator } from '../../TextDimensionCalculator.js';
Point, import { BaseAxis } from './BaseAxis.js';
DrawableElem, import { log } from '../../../../../logger.js';
BoundingRect,
OrientationEnum,
XYChartConfig,
} from '../../Interfaces.js';
import { IAxis } from './index.js';
export class LinearAxis implements IAxis { export class LinearAxis extends BaseAxis {
private scale: ScaleLinear<number, number>; private scale: ScaleLinear<number, number>;
private boundingRect: BoundingRect;
private orientation: OrientationEnum;
private domain: [number, number]; private domain: [number, number];
private range: [number, number];
constructor(private chartConfig: XYChartConfig, domain: [number, number]) { constructor(
axisConfig: AxisConfig,
domain: [number, number],
title: string,
textDimensionCalculator: ITextDimensionCalculator
) {
super(axisConfig, title, textDimensionCalculator);
this.domain = domain; this.domain = domain;
this.range = [0, 10]; this.scale = scaleLinear().domain(this.domain).range(this.getRange());
this.scale = scaleLinear().domain(this.domain).range(this.range);
this.boundingRect = { x: 0, y: 0, width: 0, height: 0 };
this.orientation = OrientationEnum.VERTICAL;
} }
setRange(range: [number, number]): void { getTickValues(): (string | number)[] {
this.range = range; return this.scale.ticks();
this.scale = scaleLinear().domain(this.domain).range(this.range);
} }
setOrientation(orientation: OrientationEnum): void { recalculateScale(): void {
this.orientation = orientation; if (this.axisPosition === 'left') {
this.domain.reverse(); // since yaxis in svg start from top
}
this.scale = scaleLinear().domain(this.domain).range(this.getRange());
log.trace('Linear axis final domain, range: ', this.domain, this.getRange());
} }
getScaleValue(value: number): number { getScaleValue(value: number): number {
return this.scale(value); return this.scale(value);
} }
calculateSpace(availableSpace: Dimension): Dimension {
return {
width: availableSpace.width,
height: availableSpace.height,
};
}
setBoundingBoxXY(point: Point): void {
this.boundingRect.x = point.x;
this.boundingRect.y = point.y;
}
getDrawableElements(): DrawableElem[] {
return [];
}
} }

View File

@ -1,17 +1,19 @@
import { import {
AxisDataType, AxisConfig,
BandAxisDataType, AxisDataType,
BoundingRect, BandAxisDataType,
LinearAxisDataType, LinearAxisDataType
XYChartConfig,
XYChartData,
} from '../../Interfaces.js'; } from '../../Interfaces.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 interface IAxis extends ChartComponent { export interface IAxis extends ChartComponent {
getScaleValue(value: string | number): number; getScaleValue(value: string | number): number;
setAxisPosition(axisPosition: AxisPosition): void;
setRange(range: [number, number]): void; setRange(range: [number, number]): void;
} }
@ -23,9 +25,10 @@ function isBandAxisData(data: any): data is BandAxisDataType {
return data.categories && Array.isArray(data.categories); return data.categories && Array.isArray(data.categories);
} }
export function getAxis(data: AxisDataType, chartConfig: XYChartConfig): IAxis { export function getAxis(data: AxisDataType, axisConfig: AxisConfig): IAxis {
const textDimansionCalculator = new TextDimensionCalculator();
if (isBandAxisData(data)) { if (isBandAxisData(data)) {
return new BandAxis(chartConfig, data.categories); return new BandAxis(axisConfig, data.categories, data.title, textDimansionCalculator);
} }
return new LinearAxis(chartConfig, [data.min, data.max]); return new LinearAxis(axisConfig, [data.min, data.max], data.title, textDimansionCalculator);
} }

View File

@ -2,12 +2,11 @@
import { defaultConfig } from '../../../config.js'; import { defaultConfig } from '../../../config.js';
import { log } from '../../../logger.js'; import { log } from '../../../logger.js';
import { import {
ChartPlotEnum, ChartPlotEnum,
DrawableElem, DrawableElem,
XYChartConfig, OrientationEnum,
XYChartData, XYChartConfig,
OrientationEnum, XYChartData
XYChartYAxisPosition,
} from './Interfaces.js'; } from './Interfaces.js';
import { Orchestrator } from './Orchestrator.js'; import { Orchestrator } from './Orchestrator.js';
@ -17,22 +16,33 @@ export class XYChartBuilder {
constructor() { constructor() {
this.config = { this.config = {
width: 500, width: 700,
height: 500, height: 500,
fontFamily: defaultConfig.fontFamily || 'Sans', fontFamily: defaultConfig.fontFamily || 'Sans',
titleFontSize: 16, titleFontSize: 16,
titleFill: '#000000', titleFill: '#000000',
titlePadding: 5, titlePadding: 5,
xAxisFontSize: 14, showtitle: true,
xAxisTitleFontSize: 16, yAxis: {
yAxisFontSize: 14, showLabel: true,
yAxisTitleFontSize: 16, labelFontSize: 14,
yAxisPosition: XYChartYAxisPosition.LEFT, lablePadding: 5,
showChartTitle: true, labelColor: '#000000',
showXAxisLable: true, showTitle: true,
showXAxisTitle: true, titleFontSize: 16,
showYAxisLabel: true, titlePadding: 5,
showYAxisTitle: true, titleColor: '#000000',
},
xAxis: {
showLabel: true,
labelFontSize: 14,
lablePadding: 5,
labelColor: '#000000',
showTitle: true,
titleFontSize: 16,
titlePadding: 5,
titleColor: '#000000',
},
chartOrientation: OrientationEnum.HORIZONTAL, chartOrientation: OrientationEnum.HORIZONTAL,
plotReservedSpacePercent: 50, plotReservedSpacePercent: 50,
}; };

View File

@ -1,13 +1,13 @@
import { select, scaleOrdinal, scaleLinear, axisBottom, line } from 'd3'; import { select } from 'd3';
import { Diagram } from '../../Diagram.js';
import * as configApi from '../../config.js'; import * as configApi from '../../config.js';
import { log } from '../../logger.js'; import { log } from '../../logger.js';
import { configureSvgSize } from '../../setupGraphViewbox.js'; import { configureSvgSize } from '../../setupGraphViewbox.js';
import { Diagram } from '../../Diagram.js';
import { import {
DrawableElem, DrawableElem,
TextElem, TextElem,
TextHorizontalPos, TextHorizontalPos,
TextVerticalPos, TextVerticalPos,
} from './chartBuilder/Interfaces.js'; } from './chartBuilder/Interfaces.js';
export const draw = (txt: string, id: string, _version: string, diagObj: Diagram) => { export const draw = (txt: string, id: string, _version: string, diagObj: Diagram) => {
@ -16,7 +16,7 @@ export const draw = (txt: string, id: string, _version: string, diagObj: Diagram
} }
function getTextAnchor(verticalPos: TextVerticalPos) { function getTextAnchor(verticalPos: TextVerticalPos) {
return verticalPos === 'left' ? 'start' : 'middle'; return verticalPos === 'left' ? 'start' : verticalPos === 'right' ? 'end' : 'middle';
} }
function getTextTransformation(data: TextElem) { function getTextTransformation(data: TextElem) {
@ -32,16 +32,13 @@ export const draw = (txt: string, id: string, _version: string, diagObj: Diagram
if (securityLevel === 'sandbox') { if (securityLevel === 'sandbox') {
sandboxElement = select('#i' + id); sandboxElement = select('#i' + id);
} }
const root = const root = sandboxElement ? sandboxElement : select('body');
sandboxElement
? sandboxElement
: select('body');
const svg = root.select(`[id="${id}"]`); const svg = root.select(`[id="${id}"]`);
const group = svg.append('g').attr('class', 'main'); const group = svg.append('g').attr('class', 'main');
const width = 500; const width = 700;
const height = 500; const height = 500;
// @ts-ignore: TODO Fix ts errors // @ts-ignore: TODO Fix ts errors
@ -74,7 +71,6 @@ export const draw = (txt: string, id: string, _version: string, diagObj: Diagram
const shapeGroup = group.append('g').attr('class', shape.groupText); const shapeGroup = group.append('g').attr('class', shape.groupText);
switch (shape.type) { switch (shape.type) {
case 'rect': case 'rect':
shapeGroup shapeGroup
@ -82,13 +78,13 @@ export const draw = (txt: string, id: string, _version: string, diagObj: Diagram
.data(shape.data) .data(shape.data)
.enter() .enter()
.append('rect') .append('rect')
.attr('x', data => data.x) .attr('x', (data) => data.x)
.attr('y', data => data.y) .attr('y', (data) => data.y)
.attr('width', data => data.width) .attr('width', (data) => data.width)
.attr('height', data => data.height) .attr('height', (data) => data.height)
.attr('fill', data => data.fill) .attr('fill', (data) => data.fill)
.attr('stroke', data => data.strokeFill) .attr('stroke', (data) => data.strokeFill)
.attr('stroke-width', data => data.strokeWidth); .attr('stroke-width', (data) => data.strokeWidth);
break; break;
case 'text': case 'text':
shapeGroup shapeGroup
@ -98,12 +94,12 @@ export const draw = (txt: string, id: string, _version: string, diagObj: Diagram
.append('text') .append('text')
.attr('x', 0) .attr('x', 0)
.attr('y', 0) .attr('y', 0)
.attr('fill', data => data.fill) .attr('fill', (data) => data.fill)
.attr('font-size', data => data.fontSize) .attr('font-size', (data) => data.fontSize)
.attr('dominant-baseline', data => getDominantBaseLine(data.horizontalPos)) .attr('dominant-baseline', (data) => getDominantBaseLine(data.horizontalPos))
.attr('text-anchor', data => getTextAnchor(data.verticalPos)) .attr('text-anchor', (data) => getTextAnchor(data.verticalPos))
.attr('transform', data => getTextTransformation(data)) .attr('transform', (data) => getTextTransformation(data))
.text(data => data.text); .text((data) => data.text);
break; break;
case 'path': case 'path':
shapeGroup shapeGroup
@ -111,10 +107,10 @@ export const draw = (txt: string, id: string, _version: string, diagObj: Diagram
.data(shape.data) .data(shape.data)
.enter() .enter()
.append('path') .append('path')
.attr('d', data => data.path) .attr('d', (data) => data.path)
.attr('fill', data => data.fill? data.fill: "none") .attr('fill', (data) => (data.fill ? data.fill : 'none'))
.attr('stroke', data => data.strokeFill) .attr('stroke', (data) => data.strokeFill)
.attr('stroke-width', data => data.strokeWidth) .attr('stroke-width', (data) => data.strokeWidth);
break; break;
} }
} }