mermaid/packages/mermaid/src/diagrams/quadrant-chart/quadrantRenderer.ts

176 lines
6.0 KiB
TypeScript

// @ts-nocheck - don't check until handle it
import { select } from 'd3';
import { getConfig } from '../../diagram-api/diagramAPI.js';
import { log } from '../../logger.js';
import { configureSvgSize } from '../../setupGraphViewbox.js';
import type { Diagram } from '../../Diagram.js';
import type {
QuadrantBuildType,
QuadrantLineType,
QuadrantPointType,
QuadrantQuadrantsType,
QuadrantTextType,
TextHorizontalPos,
TextVerticalPos,
} from './quadrantBuilder.js';
export const draw = (txt: string, id: string, _version: string, diagObj: Diagram) => {
function getDominantBaseLine(horizontalPos: TextHorizontalPos) {
return horizontalPos === 'top' ? 'hanging' : 'middle';
}
function getTextAnchor(verticalPos: TextVerticalPos) {
return verticalPos === 'left' ? 'start' : 'middle';
}
function getTransformation(data: { x: number; y: number; rotation: number }) {
return `translate(${data.x}, ${data.y}) rotate(${data.rotation || 0})`;
}
const conf = getConfig();
log.debug('Rendering quadrant chart\n' + txt);
const securityLevel = conf.securityLevel;
// Handle root and Document for when rendering in sandbox mode
let sandboxElement;
if (securityLevel === 'sandbox') {
sandboxElement = select('#i' + id);
}
const root =
securityLevel === 'sandbox'
? select(sandboxElement.nodes()[0].contentDocument.body)
: select('body');
const svg = root.select(`[id="${id}"]`);
const group = svg.append('g').attr('class', 'main');
const width = conf.quadrantChart?.chartWidth || 500;
const height = conf.quadrantChart?.chartHeight || 500;
configureSvgSize(svg, height, width, conf.quadrantChart?.useMaxWidth || true);
svg.attr('viewBox', '0 0 ' + width + ' ' + height);
// @ts-ignore: TODO Fix ts errors
diagObj.db.setHeight(height);
// @ts-ignore: TODO Fix ts errors
diagObj.db.setWidth(width);
// @ts-ignore: TODO Fix ts errors
const quadrantData: QuadrantBuildType = diagObj.db.getQuadrantData();
const quadrantsGroup = group.append('g').attr('class', 'quadrants');
const borderGroup = group.append('g').attr('class', 'border');
const dataPointGroup = group.append('g').attr('class', 'data-points');
const labelGroup = group.append('g').attr('class', 'labels');
const titleGroup = group.append('g').attr('class', 'title');
if (quadrantData.title) {
titleGroup
.append('text')
.attr('x', 0)
.attr('y', 0)
.attr('fill', quadrantData.title.fill)
.attr('font-size', quadrantData.title.fontSize)
.attr('dominant-baseline', getDominantBaseLine(quadrantData.title.horizontalPos))
.attr('text-anchor', getTextAnchor(quadrantData.title.verticalPos))
.attr('transform', getTransformation(quadrantData.title))
.text(quadrantData.title.text);
}
if (quadrantData.borderLines) {
borderGroup
.selectAll('line')
.data(quadrantData.borderLines)
.enter()
.append('line')
.attr('x1', (data: QuadrantLineType) => data.x1)
.attr('y1', (data: QuadrantLineType) => data.y1)
.attr('x2', (data: QuadrantLineType) => data.x2)
.attr('y2', (data: QuadrantLineType) => data.y2)
.style('stroke', (data: QuadrantLineType) => data.strokeFill)
.style('stroke-width', (data: QuadrantLineType) => data.strokeWidth);
}
const quadrants = quadrantsGroup
.selectAll('g.quadrant')
.data(quadrantData.quadrants)
.enter()
.append('g')
.attr('class', 'quadrant');
quadrants
.append('rect')
.attr('x', (data: QuadrantQuadrantsType) => data.x)
.attr('y', (data: QuadrantQuadrantsType) => data.y)
.attr('width', (data: QuadrantQuadrantsType) => data.width)
.attr('height', (data: QuadrantQuadrantsType) => data.height)
.attr('fill', (data: QuadrantQuadrantsType) => data.fill);
quadrants
.append('text')
.attr('x', 0)
.attr('y', 0)
.attr('fill', (data: QuadrantQuadrantsType) => data.text.fill)
.attr('font-size', (data: QuadrantQuadrantsType) => data.text.fontSize)
.attr('dominant-baseline', (data: QuadrantQuadrantsType) =>
getDominantBaseLine(data.text.horizontalPos)
)
.attr('text-anchor', (data: QuadrantQuadrantsType) => getTextAnchor(data.text.verticalPos))
.attr('transform', (data: QuadrantQuadrantsType) => getTransformation(data.text))
.text((data: QuadrantQuadrantsType) => data.text.text);
const labels = labelGroup
.selectAll('g.label')
.data(quadrantData.axisLabels)
.enter()
.append('g')
.attr('class', 'label');
labels
.append('text')
.attr('x', 0)
.attr('y', 0)
.text((data: QuadrantTextType) => data.text)
.attr('fill', (data: QuadrantTextType) => data.fill)
.attr('font-size', (data: QuadrantTextType) => data.fontSize)
.attr('dominant-baseline', (data: QuadrantTextType) => getDominantBaseLine(data.horizontalPos))
.attr('text-anchor', (data: QuadrantTextType) => getTextAnchor(data.verticalPos))
.attr('transform', (data: QuadrantTextType) => getTransformation(data));
const dataPoints = dataPointGroup
.selectAll('g.data-point')
.data(quadrantData.points)
.enter()
.append('g')
.attr('class', 'data-point');
dataPoints
.append('circle')
.attr('cx', (data: QuadrantPointType) => data.x)
.attr('cy', (data: QuadrantPointType) => data.y)
.attr('r', (data: QuadrantPointType) => data.radius)
.attr('fill', (data: QuadrantPointType) => data.fill)
.attr('stroke', (data: QuadrantPointType) => data.strokeColor)
.attr('stroke-width', (data: QuadrantPointType) => data.strokeWidth);
dataPoints
.append('text')
.attr('x', 0)
.attr('y', 0)
.text((data: QuadrantPointType) => data.text.text)
.attr('fill', (data: QuadrantPointType) => data.text.fill)
.attr('font-size', (data: QuadrantPointType) => data.text.fontSize)
.attr('dominant-baseline', (data: QuadrantPointType) =>
getDominantBaseLine(data.text.horizontalPos)
)
.attr('text-anchor', (data: QuadrantPointType) => getTextAnchor(data.text.verticalPos))
.attr('transform', (data: QuadrantPointType) => getTransformation(data.text));
};
export default {
draw,
};