MrBlenny / react-flow-chart

🌊 A flexible, stateless, declarative flow chart library for react.
https://mrblenny.github.io/react-flow-chart/index.html
MIT License
1.46k stars 307 forks source link

Automatic layout #61

Closed jakub-zawislak closed 4 years ago

jakub-zawislak commented 4 years ago

It would be nice to have an automatic layout feature.

Here is my example using dagre:

Chart data

const chart = {
  nodes: {
    node1: {
      id: "node1",
      ports: // ...
      // there is no need for `position` key in the node
     }
  edges: // ...
}

Initialize dagre

import dagre from 'dagre'

const g = new dagre.graphlib.Graph()
g.setGraph({})
g.setDefaultEdgeLabel(function() { return {}; })

Calculate layout:

for (let nodeId in chart.nodes) {
  // you need to know dimension of every node
  g.setNode(nodeId, { width: 200, height: 100 });
}

for (let k in chart.links) {
  g.setEdge(chart.links[k].from.nodeId, chart.links[k].to.nodeId);
}

dagre.layout(g);

Save it to the chart variable:

for (let nodeId in chart.nodes) {
  chart.nodes[nodeId].position = {
    x: g.node(nodeId).x - 200 / 2, // dagre gives position from the center of node
    y: g.node(nodeId).y - 100 / 2
  }
}

Downside of calculating it before rendering is that we may don't know sizes of nodes.

MehdiSaffar commented 4 years ago

That's a really nice idea! Could you post a quick codesandbox to see what kind of result it gives?

jakub-zawislak commented 4 years ago

Example on codesandbox

I also tried to trigger the layout calculating after the first render of chart to get the sizes of nodes from DOM. Unfortunately, this approach didn't work if some nodes are not visible on screen, because they are not rendered in DOM. Eventually, I decided that I don't need nodes with variable dimensions in my project.

MrBlenny commented 4 years ago

Try smartRouting https://mrblenny.github.io/react-flow-chart/index.html?path=/story/other-config--smart-link-routing https://github.com/MrBlenny/react-flow-chart/blob/master/stories/SmartRouting.tsx

johan-lejdung commented 3 years ago

SmartRouting doesn't seem to do what's requested by the OP though. The example you linked to still have to set their position manually