mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-08-15 06:19:24 +02:00
adjusted layout and theme support
This commit is contained in:
@@ -16,7 +16,7 @@ const defaultTreemapData: TreemapData = {
|
|||||||
nodes: [],
|
nodes: [],
|
||||||
levels: new Map(),
|
levels: new Map(),
|
||||||
};
|
};
|
||||||
|
let outerNodes: TreemapNode[] = [];
|
||||||
let data: TreemapData = structuredClone(defaultTreemapData);
|
let data: TreemapData = structuredClone(defaultTreemapData);
|
||||||
|
|
||||||
const getConfig = () => {
|
const getConfig = () => {
|
||||||
@@ -32,17 +32,22 @@ const addNode = (node: TreemapNode, level: number) => {
|
|||||||
data.nodes.push(node);
|
data.nodes.push(node);
|
||||||
data.levels.set(node, level);
|
data.levels.set(node, level);
|
||||||
|
|
||||||
|
if (level === 0) {
|
||||||
|
outerNodes.push(node);
|
||||||
|
}
|
||||||
|
|
||||||
// Set the root node if this is a level 0 node and we don't have a root yet
|
// Set the root node if this is a level 0 node and we don't have a root yet
|
||||||
if (level === 0 && !data.root) {
|
if (level === 0 && !data.root) {
|
||||||
data.root = node;
|
data.root = node;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getRoot = (): TreemapNode | undefined => data.root;
|
const getRoot = (): TreemapNode | undefined => ({ name: '', children: outerNodes });
|
||||||
|
|
||||||
const clear = () => {
|
const clear = () => {
|
||||||
commonClear();
|
commonClear();
|
||||||
data = structuredClone(defaultTreemapData);
|
data = structuredClone(defaultTreemapData);
|
||||||
|
outerNodes = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
export const db: TreemapDB = {
|
export const db: TreemapDB = {
|
||||||
|
@@ -1,11 +1,14 @@
|
|||||||
import type { Diagram } from '../../Diagram.js';
|
import type { Diagram } from '../../Diagram.js';
|
||||||
import type { DiagramRenderer, DrawDefinition } from '../../diagram-api/types.js';
|
import type { DiagramRenderer, DrawDefinition } from '../../diagram-api/types.js';
|
||||||
import { selectSvgElement } from '../../rendering-util/selectSvgElement.js';
|
import { selectSvgElement } from '../../rendering-util/selectSvgElement.js';
|
||||||
|
import { setupViewPortForSVG } from '../../rendering-util/setupViewPortForSVG.js';
|
||||||
import { configureSvgSize } from '../../setupGraphViewbox.js';
|
import { configureSvgSize } from '../../setupGraphViewbox.js';
|
||||||
import type { TreemapDB, TreemapNode } from './types.js';
|
import type { TreemapDB, TreemapNode } from './types.js';
|
||||||
import { scaleOrdinal, treemap, hierarchy, format, select } from 'd3';
|
import { scaleOrdinal, treemap, hierarchy, format, select } from 'd3';
|
||||||
|
import { getConfig } from '../../config.js';
|
||||||
|
|
||||||
const DEFAULT_INNER_PADDING = 5; // Default for inner padding between cells/sections
|
const DEFAULT_INNER_PADDING = 10; // Default for inner padding between cells/sections
|
||||||
|
const SECTION_INNER_PADDING = 10; // Default for inner padding between cells/sections
|
||||||
const SECTION_HEADER_HEIGHT = 25;
|
const SECTION_HEADER_HEIGHT = 25;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -17,7 +20,9 @@ const draw: DrawDefinition = (_text, id, _version, diagram: Diagram) => {
|
|||||||
const treemapInnerPadding = config.padding !== undefined ? config.padding : DEFAULT_INNER_PADDING;
|
const treemapInnerPadding = config.padding !== undefined ? config.padding : DEFAULT_INNER_PADDING;
|
||||||
const title = treemapDb.getDiagramTitle();
|
const title = treemapDb.getDiagramTitle();
|
||||||
const root = treemapDb.getRoot();
|
const root = treemapDb.getRoot();
|
||||||
|
// const theme = config.getThemeVariables();
|
||||||
|
const { themeVariables } = getConfig();
|
||||||
|
console.log('root', root);
|
||||||
if (!root) {
|
if (!root) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -27,8 +32,8 @@ const draw: DrawDefinition = (_text, id, _version, diagram: Diagram) => {
|
|||||||
|
|
||||||
const svg = selectSvgElement(id);
|
const svg = selectSvgElement(id);
|
||||||
// Use config dimensions or defaults
|
// Use config dimensions or defaults
|
||||||
const width = config.nodeWidth ? config.nodeWidth * 10 : 960;
|
const width = config.nodeWidth ? config.nodeWidth * SECTION_INNER_PADDING : 960;
|
||||||
const height = config.nodeHeight ? config.nodeHeight * 10 : 500;
|
const height = config.nodeHeight ? config.nodeHeight * SECTION_INNER_PADDING : 500;
|
||||||
|
|
||||||
const svgWidth = width;
|
const svgWidth = width;
|
||||||
const svgHeight = height + titleHeight;
|
const svgHeight = height + titleHeight;
|
||||||
@@ -42,16 +47,49 @@ const draw: DrawDefinition = (_text, id, _version, diagram: Diagram) => {
|
|||||||
|
|
||||||
// Create color scale
|
// Create color scale
|
||||||
const colorScale = scaleOrdinal<string>().range([
|
const colorScale = scaleOrdinal<string>().range([
|
||||||
'#8dd3c7',
|
'transparent',
|
||||||
'#ffffb3',
|
themeVariables.cScale0,
|
||||||
'#bebada',
|
themeVariables.cScale1,
|
||||||
'#fb8072',
|
themeVariables.cScale2,
|
||||||
'#80b1d3',
|
themeVariables.cScale3,
|
||||||
'#fdb462',
|
themeVariables.cScale4,
|
||||||
'#b3de69',
|
themeVariables.cScale5,
|
||||||
'#fccde5',
|
themeVariables.cScale6,
|
||||||
'#d9d9d9',
|
themeVariables.cScale7,
|
||||||
'#bc80bd',
|
themeVariables.cScale8,
|
||||||
|
themeVariables.cScale9,
|
||||||
|
themeVariables.cScale10,
|
||||||
|
themeVariables.cScale11,
|
||||||
|
]);
|
||||||
|
const colorScalePeer = scaleOrdinal<string>().range([
|
||||||
|
'transparent',
|
||||||
|
themeVariables.cScalePeer0,
|
||||||
|
themeVariables.cScalePeer1,
|
||||||
|
themeVariables.cScalePeer2,
|
||||||
|
themeVariables.cScalePeer3,
|
||||||
|
themeVariables.cScalePeer4,
|
||||||
|
themeVariables.cScalePeer5,
|
||||||
|
themeVariables.cScalePeer6,
|
||||||
|
themeVariables.cScalePeer7,
|
||||||
|
themeVariables.cScalePeer8,
|
||||||
|
themeVariables.cScalePeer9,
|
||||||
|
themeVariables.cScalePeer10,
|
||||||
|
themeVariables.cScalePeer11,
|
||||||
|
]);
|
||||||
|
const colorScaleLabel = scaleOrdinal<string>().range([
|
||||||
|
'transparent',
|
||||||
|
themeVariables.cScaleLabel0,
|
||||||
|
themeVariables.cScaleLabel1,
|
||||||
|
themeVariables.cScaleLabel2,
|
||||||
|
themeVariables.cScaleLabel3,
|
||||||
|
themeVariables.cScaleLabel4,
|
||||||
|
themeVariables.cScaleLabel5,
|
||||||
|
themeVariables.cScaleLabel6,
|
||||||
|
themeVariables.cScaleLabel7,
|
||||||
|
themeVariables.cScaleLabel8,
|
||||||
|
themeVariables.cScaleLabel9,
|
||||||
|
themeVariables.cScaleLabel10,
|
||||||
|
themeVariables.cScaleLabel11,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Draw the title if it exists
|
// Draw the title if it exists
|
||||||
@@ -80,8 +118,13 @@ const draw: DrawDefinition = (_text, id, _version, diagram: Diagram) => {
|
|||||||
// Create treemap layout
|
// Create treemap layout
|
||||||
const treemapLayout = treemap<TreemapNode>()
|
const treemapLayout = treemap<TreemapNode>()
|
||||||
.size([width, height])
|
.size([width, height])
|
||||||
.paddingTop((d) => (d.children && d.children.length > 0 ? SECTION_HEADER_HEIGHT : 0))
|
.paddingTop((d) =>
|
||||||
|
d.children && d.children.length > 0 ? SECTION_HEADER_HEIGHT + SECTION_INNER_PADDING : 0
|
||||||
|
)
|
||||||
.paddingInner(treemapInnerPadding)
|
.paddingInner(treemapInnerPadding)
|
||||||
|
.paddingLeft((d) => (d.children && d.children.length > 0 ? SECTION_INNER_PADDING : 0))
|
||||||
|
.paddingRight((d) => (d.children && d.children.length > 0 ? SECTION_INNER_PADDING : 0))
|
||||||
|
.paddingBottom((d) => (d.children && d.children.length > 0 ? SECTION_INNER_PADDING : 0))
|
||||||
.round(true);
|
.round(true);
|
||||||
|
|
||||||
// Apply the treemap layout to the hierarchy
|
// Apply the treemap layout to the hierarchy
|
||||||
@@ -103,11 +146,22 @@ const draw: DrawDefinition = (_text, id, _version, diagram: Diagram) => {
|
|||||||
.attr('width', (d) => d.x1 - d.x0)
|
.attr('width', (d) => d.x1 - d.x0)
|
||||||
.attr('height', SECTION_HEADER_HEIGHT)
|
.attr('height', SECTION_HEADER_HEIGHT)
|
||||||
.attr('class', 'treemapSectionHeader')
|
.attr('class', 'treemapSectionHeader')
|
||||||
|
// .attr('fill', (d) => colorScale(d.data.name))
|
||||||
|
.attr('fill', 'none')
|
||||||
|
.attr('fill-opacity', 0.6)
|
||||||
|
// .attr('stroke', (d) => colorScale(d.data.name))
|
||||||
|
.attr('stroke-width', 0.6);
|
||||||
|
|
||||||
|
sections
|
||||||
|
.append('rect')
|
||||||
|
.attr('width', (d) => d.x1 - d.x0)
|
||||||
|
.attr('height', (d) => d.y1 - d.y0)
|
||||||
|
.attr('class', 'treemapSection')
|
||||||
.attr('fill', (d) => colorScale(d.data.name))
|
.attr('fill', (d) => colorScale(d.data.name))
|
||||||
.attr('fill-opacity', 0.6)
|
.attr('fill-opacity', 0.6)
|
||||||
.attr('stroke', (d) => colorScale(d.data.name))
|
.attr('stroke', (d) => colorScalePeer(d.data.name))
|
||||||
.attr('stroke-width', 1);
|
.attr('stroke-width', 2.0)
|
||||||
|
.attr('stroke-opacity', 0.4);
|
||||||
// Add section labels
|
// Add section labels
|
||||||
sections
|
sections
|
||||||
.append('text')
|
.append('text')
|
||||||
@@ -118,7 +172,7 @@ const draw: DrawDefinition = (_text, id, _version, diagram: Diagram) => {
|
|||||||
.text((d) => d.data.name)
|
.text((d) => d.data.name)
|
||||||
.attr('font-weight', 'bold')
|
.attr('font-weight', 'bold')
|
||||||
.style('font-size', '12px')
|
.style('font-size', '12px')
|
||||||
.style('fill', '#000000')
|
.style('fill', (d) => colorScaleLabel(d.data.name))
|
||||||
.each(function (d) {
|
.each(function (d) {
|
||||||
const self = select(this);
|
const self = select(this);
|
||||||
const originalText = d.data.name;
|
const originalText = d.data.name;
|
||||||
@@ -173,7 +227,7 @@ const draw: DrawDefinition = (_text, id, _version, diagram: Diagram) => {
|
|||||||
.text((d) => (d.value ? valueFormat(d.value) : ''))
|
.text((d) => (d.value ? valueFormat(d.value) : ''))
|
||||||
.attr('font-style', 'italic')
|
.attr('font-style', 'italic')
|
||||||
.style('font-size', '10px')
|
.style('font-size', '10px')
|
||||||
.style('fill', '#000000');
|
.style('fill', (d) => colorScaleLabel(d.data.name));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw the leaf nodes
|
// Draw the leaf nodes
|
||||||
@@ -193,13 +247,18 @@ const draw: DrawDefinition = (_text, id, _version, diagram: Diagram) => {
|
|||||||
.attr('height', (d) => d.y1 - d.y0)
|
.attr('height', (d) => d.y1 - d.y0)
|
||||||
.attr('class', 'treemapLeaf')
|
.attr('class', 'treemapLeaf')
|
||||||
.attr('fill', (d) => {
|
.attr('fill', (d) => {
|
||||||
let current = d;
|
// Leaves inherit color from their immediate parent section's name.
|
||||||
while (current.depth > 1 && current.parent) {
|
// If a leaf is the root itself (no parent), it uses its own name.
|
||||||
current = current.parent;
|
return d.parent ? colorScale(d.parent.data.name) : colorScale(d.data.name);
|
||||||
}
|
|
||||||
return colorScale(current.data.name);
|
|
||||||
})
|
})
|
||||||
.attr('fill-opacity', 0.8);
|
.attr('fill-opacity', 0.2)
|
||||||
|
.attr('stroke', (d) => {
|
||||||
|
// Leaves inherit color from their immediate parent section's name.
|
||||||
|
// If a leaf is the root itself (no parent), it uses its own name.
|
||||||
|
return d.parent ? colorScale(d.parent.data.name) : colorScale(d.data.name);
|
||||||
|
})
|
||||||
|
.attr('stroke-width', 2.0)
|
||||||
|
.attr('stroke-opacity', 0.3);
|
||||||
|
|
||||||
// Add clip paths to prevent text from extending outside nodes
|
// Add clip paths to prevent text from extending outside nodes
|
||||||
cell
|
cell
|
||||||
@@ -215,7 +274,9 @@ const draw: DrawDefinition = (_text, id, _version, diagram: Diagram) => {
|
|||||||
.attr('class', 'treemapLabel')
|
.attr('class', 'treemapLabel')
|
||||||
.attr('x', 4)
|
.attr('x', 4)
|
||||||
.attr('y', 14)
|
.attr('y', 14)
|
||||||
.style('font-size', '11px')
|
.style('font-size', '34px')
|
||||||
|
.style('fill', (d) => colorScaleLabel(d.data.name))
|
||||||
|
// .style('stroke', (d) => colorScaleLabel(d.data.name))
|
||||||
.attr('clip-path', (d, i) => `url(#clip-${id}-${i})`)
|
.attr('clip-path', (d, i) => `url(#clip-${id}-${i})`)
|
||||||
.text((d) => d.data.name);
|
.text((d) => d.data.name);
|
||||||
|
|
||||||
@@ -246,6 +307,25 @@ const draw: DrawDefinition = (_text, id, _version, diagram: Diagram) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setupViewPortForSVG(svg, 0, 'flowchart', config?.useMaxWidth || false);
|
||||||
|
const viewBox = svg.attr('viewBox');
|
||||||
|
const viewBoxParts = viewBox.split(' ');
|
||||||
|
const viewBoxWidth = viewBoxParts[2];
|
||||||
|
const viewBoxHeight = viewBoxParts[3];
|
||||||
|
const viewBoxX = viewBoxParts[0];
|
||||||
|
const viewBoxY = viewBoxParts[1];
|
||||||
|
|
||||||
|
const viewBoxWidthNumber = Number(viewBoxWidth);
|
||||||
|
const viewBoxHeightNumber = Number(viewBoxHeight);
|
||||||
|
const viewBoxXNumber = Number(viewBoxX);
|
||||||
|
const viewBoxYNumber = Number(viewBoxY);
|
||||||
|
|
||||||
|
// Adjust the viewBox to account for the title height
|
||||||
|
svg.attr(
|
||||||
|
'viewBox',
|
||||||
|
`${viewBoxXNumber} ${viewBoxYNumber + SECTION_HEADER_HEIGHT} ${viewBoxWidthNumber} ${viewBoxHeightNumber - SECTION_HEADER_HEIGHT}`
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const renderer: DiagramRenderer = { draw };
|
export const renderer: DiagramRenderer = { draw };
|
||||||
|
@@ -22,9 +22,8 @@ export const getStyles: DiagramStylesProvider = ({
|
|||||||
|
|
||||||
return `
|
return `
|
||||||
.treemapNode {
|
.treemapNode {
|
||||||
fill: pink;
|
// stroke: black;
|
||||||
stroke: black;
|
// stroke-width: 1;
|
||||||
stroke-width: 1;
|
|
||||||
}
|
}
|
||||||
.packetByte {
|
.packetByte {
|
||||||
font-size: ${options.byteFontSize};
|
font-size: ${options.byteFontSize};
|
||||||
|
Reference in New Issue
Block a user