elk icon indicating copy to clipboard operation
elk copied to clipboard

Incorrect position of nodes in case of multiple source handles in a node (Elkjs not considering port order)

Open abdelazkamo opened this issue 2 years ago • 2 comments

I'm building a node-based system using ReactFlow and using Elkjs to layout the nodes horizontally, but they are not positioned in the correct order in case of multiple handles in a specific node. I think elkjs doesn't take port order into account. Please take a look at my getLayoutedElements function and tell me how I can solve this problem.

Current result:

1

expected result:

2

   const getLayoutedElements = (nodes, edges) => {
      if (nodes.length > 0) {

      const elkOptions = {
         'elk.algorithm': 'layered',
         'elk.layered.spacing.nodeNodeBetweenLayers': '100',
         'elk.layered.nodePlacement.strategy': 'NETWORK_SIMPLEX',
         'elk.spacing.nodeNode': '80',
         'elk.hierarchyHandling': 'INCLUDE_CHILDREN',
      };

         const graph = {
            id: 'root',
            layoutOptions: elkOptions ,
            children: nodes.map((n) => {
               const symbolprop = Object.getOwnPropertySymbols(n);
               const handleBounds = n[symbolprop[0]].handleBounds;
               const sources = handleBounds.source && handleBounds.source;

               const sourcePorts = sources
                  ? sources.map((s, si) => ({
                       id: s.id,
                       order: si,
                    }))
                  : [{ id: n.id, order: 0 }];

               return {
                  ...n,
                  ports: [{ id: n.id }, ...sourcePorts],
               };
            }),

            edges: edges.map((e) => ({
               id: e.id,
               sources: [e.sourceHandle || e.source],
               targets: [e.target],
            })),
         };

         return elk
            .layout(graph)
            .then((layoutedGraph) => {
               return {
                  nodes: layoutedGraph.children.map((node) => ({
                     ...node,
                     position: { x: node.x, y: node.y },
                  })),
                  edges: layoutedGraph.edges,
               };
            })
            .catch(console.error);
      }
   };

abdelazkamo avatar Nov 11 '23 07:11 abdelazkamo

Can you replicate your problem in elklive?

soerendomroes avatar Nov 13 '23 10:11 soerendomroes

Yes, thank you

abdelazkamo avatar Nov 13 '23 10:11 abdelazkamo