mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-09-12 11:59:39 +02:00
Layout algorithm in place
This commit is contained in:
@@ -2,7 +2,9 @@
|
||||
import { select } from 'd3';
|
||||
import { log, getConfig, setupGraphViewbox } from '../../diagram-api/diagramAPI';
|
||||
import svgDraw from './svgDraw';
|
||||
|
||||
import { BoundingBox, Layout, Tree } from 'non-layered-tidy-tree-layout';
|
||||
import clone from 'fast-clone';
|
||||
import db from './mindmapDb';
|
||||
/**
|
||||
* @param {any} svg The svg element to draw the diagram onto
|
||||
* @param {object} mindmap The maindmap data and hierarchy
|
||||
@@ -17,17 +19,181 @@ function drawNodes(svg, mindmap, conf) {
|
||||
}
|
||||
}
|
||||
|
||||
/** @param {any} svg The svg element to draw the diagram onto */
|
||||
function drawEdges() {}
|
||||
|
||||
/**
|
||||
* @param mindmap
|
||||
* @param callback
|
||||
*/
|
||||
function eachNode(mindmap, callback) {
|
||||
callback(mindmap);
|
||||
if (mindmap.children) {
|
||||
mindmap.children.forEach((child) => {
|
||||
eachNode(child, callback);
|
||||
});
|
||||
}
|
||||
}
|
||||
/** @param {object} mindmap */
|
||||
function transpose(mindmap) {
|
||||
console.log('transpose', mindmap);
|
||||
eachNode(mindmap, (node) => {
|
||||
// node.y = node.y - (node.y - bb.top) * 2 - node.height;
|
||||
const orgWidth = node.width;
|
||||
const orgX = node.x;
|
||||
node.width = node.height;
|
||||
node.height = orgWidth;
|
||||
node.x = node.y;
|
||||
node.y = orgX;
|
||||
});
|
||||
return mindmap;
|
||||
}
|
||||
/** @param {object} mindmap */
|
||||
function bottomToUp(mindmap) {
|
||||
console.log('bottomToUp', mindmap);
|
||||
eachNode(mindmap.result, (node) => {
|
||||
// node.y = node.y - (node.y - bb.top) * 2 - node.height;
|
||||
node.y = node.y - (node.y - 0) * 2 - node.height;
|
||||
});
|
||||
return mindmap;
|
||||
}
|
||||
/** @param {object} mindmap The mindmap hierarchy */
|
||||
function rightToLeft(mindmap) {
|
||||
console.log('bottomToUp', mindmap);
|
||||
eachNode(mindmap.result, (node) => {
|
||||
// node.y = node.y - (node.y - bb.top) * 2 - node.height;
|
||||
node.x = node.x - (node.x - 0) * 2 - node.width;
|
||||
});
|
||||
return mindmap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mindmap
|
||||
* @param dir
|
||||
* @param conf
|
||||
*/
|
||||
function layout(mindmap, dir, conf) {
|
||||
const bb = new BoundingBox(40, 40);
|
||||
|
||||
const layout = new Layout(bb);
|
||||
switch (dir) {
|
||||
case 'TB':
|
||||
return layout.layout(mindmap);
|
||||
case 'BT':
|
||||
return bottomToUp(layout.layout(mindmap));
|
||||
case 'RL': {
|
||||
transpose(mindmap);
|
||||
let newRes = layout.layout(mindmap);
|
||||
transpose(newRes.result);
|
||||
return rightToLeft(newRes);
|
||||
}
|
||||
case 'LR': {
|
||||
transpose(mindmap);
|
||||
let newRes = layout.layout(mindmap);
|
||||
transpose(newRes.result);
|
||||
return newRes;
|
||||
}
|
||||
default:
|
||||
}
|
||||
}
|
||||
const dirFromIndex = (index) => {
|
||||
const dirNum = index % 4;
|
||||
switch (dirNum) {
|
||||
case 0:
|
||||
return 'LR';
|
||||
case 1:
|
||||
return 'RL';
|
||||
case 2:
|
||||
return 'TB';
|
||||
case 3:
|
||||
return 'BT';
|
||||
default:
|
||||
return 'TB';
|
||||
}
|
||||
};
|
||||
|
||||
const mergeTrees = (node, trees) => {
|
||||
node.x = trees[0].result.x;
|
||||
node.y = trees[0].result.y;
|
||||
trees.forEach((tree) => {
|
||||
tree.result.children.forEach((child) => {
|
||||
const dx = node.x - tree.result.x;
|
||||
const dy = node.y - tree.result.y;
|
||||
eachNode(child, (childNode) => {
|
||||
const orgNode = db.getNodeById(childNode.id);
|
||||
if (orgNode) {
|
||||
orgNode.x = childNode.x + dx;
|
||||
orgNode.y = childNode.y + dy;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
return node;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param node
|
||||
* @param isRoot
|
||||
* @param parent
|
||||
* @param conf
|
||||
*/
|
||||
function layoutMindmap(node, isRoot) {}
|
||||
function layoutMindmap(node, conf) {
|
||||
// BoundingBox(gap, bottomPadding)
|
||||
// const bb = new BoundingBox(10, 10);
|
||||
// const layout = new Layout(bb);
|
||||
// // const layout = new HorizontalLayout(bb);
|
||||
|
||||
const trees = [];
|
||||
// node.children.forEach((child, index) => {
|
||||
// const tree = clone(node);
|
||||
// tree.children = [tree.children[index]];
|
||||
// trees.push(layout(tree, dirFromIndex(index), conf));
|
||||
// });
|
||||
|
||||
let cnt = 0;
|
||||
// For each direction, create a new tree with the same root, and add a ubset of the children to it.
|
||||
for (let i = 0; i < 4; i++) {
|
||||
// Calculate the number of the children of the root node that will be used in this direction
|
||||
const numChildren =
|
||||
Math.floor(node.children.length / 4) + (node.children.length % 4 > i ? 1 : 0);
|
||||
// Copy the original root node
|
||||
const tree = clone(node);
|
||||
// Setup the new copy with the children to be rendered in this direction
|
||||
tree.children = [];
|
||||
for (let j = 0; j < numChildren; j++) {
|
||||
tree.children.push(node.children[cnt]);
|
||||
cnt++;
|
||||
}
|
||||
if (tree.children.length > 0) {
|
||||
trees.push(layout(tree, dirFromIndex(i), conf));
|
||||
}
|
||||
}
|
||||
|
||||
// Merge the trees into a single tree
|
||||
const result = mergeTrees(node, trees);
|
||||
|
||||
// return layout(node, 'BT', conf);
|
||||
// const res = layout(node, 'BT', conf);
|
||||
// res.result.children = [];
|
||||
// trees.forEach((tree) => {
|
||||
// res.result.children.push(tree.result);
|
||||
// });
|
||||
console.log('Trees', trees);
|
||||
return node;
|
||||
}
|
||||
/**
|
||||
* @param node
|
||||
* @param isRoot
|
||||
* @param conf
|
||||
*/
|
||||
function positionNodes(node, isRoot) {}
|
||||
function positionNodes(node, conf) {
|
||||
svgDraw.positionNode(node, conf);
|
||||
if (node.children) {
|
||||
node.children.forEach((child) => {
|
||||
positionNodes(child, conf);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a an info picture in the tag with id: id based on the graph definition in text.
|
||||
@@ -63,16 +229,6 @@ export const draw = (text, id, version, diagObj) => {
|
||||
const g = svg.append('g');
|
||||
const mm = diagObj.db.getMindmap();
|
||||
|
||||
// mm.x = 0;
|
||||
// mm.y = 0;
|
||||
// svgDraw.drawNode(g, mm, getConfig());
|
||||
// mm.children.forEach((child) => {
|
||||
// child.x = 200;
|
||||
// child.y = 200;
|
||||
// child.width = 200;
|
||||
// svgDraw.drawNode(g, child, getConfig());
|
||||
// });
|
||||
|
||||
// Draw the graph and start with drawing the nodes without proper position
|
||||
// this gives us the size of the nodes and we can set the positions later
|
||||
|
||||
@@ -82,12 +238,14 @@ export const draw = (text, id, version, diagObj) => {
|
||||
|
||||
// Next step is to layout the mindmap, giving each node a position
|
||||
|
||||
// layoutMindmap(mm, conf);
|
||||
console.log('Before', mm);
|
||||
const positionedMindmap = layoutMindmap(mm, conf);
|
||||
console.log(positionedMindmap);
|
||||
|
||||
// After this we can draw, first the edges and the then nodes with the correct position
|
||||
// drawEdges(svg, mm, conf);
|
||||
|
||||
// positionNodes(svg, mm, conf);
|
||||
positionNodes(positionedMindmap, conf);
|
||||
|
||||
// Setup the view box and size of the svg element
|
||||
setupGraphViewbox(undefined, svg, conf.mindmap.diagramPadding, conf.mindmap.useMaxWidth);
|
||||
|
Reference in New Issue
Block a user