Hierarchical Layout : nodes not created as per insertion order in same level

让人想犯罪 __ 提交于 2019-12-12 22:48:42

问题


I have assigned level to each node. Now on each level, I want nodes to appear in same order in which it is inserted. That's what even documentation says. I have seen many examples where it happens and only difference with my case is: there are edges on X axis too.

Here's a snippet:

function main() {
  var graph = {
    nodes: new vis.DataSet([
      { "id": "M1", "label": "M1", "level": 0 },
      { "id": "R1", "label": "R1", "level": 0 },
      { "id": "W1", "label": "W1", "level": 0 },

      { "id": "C1R1", "label": "C1R1", "level": 1 },

      { "id": "C2R1", "label": "C2R1", "level": 1 },
      { "id": "R2R1", "label": "R2R1", "level": 1 },
      { "id": "W2R1", "label": "W2R1", "level": 1 },
      { "id": "C3R1", "label": "C3R1", "level": 1 }

    ]),
    edges: new vis.DataSet([
      { "from": "M1", "to": "R1" },
      { "from": "W1", "to": "R1" },
      { "from": "M2", "to": "R2" },
      { "from": "W2", "to": "R2" },

      { "from": "R1", "to": "C1R1" },
      { "from": "R1", "to": "C2R1" },
      { "from": "C2R1", "to": "R2R1" },
      { "from": "W2R1", "to": "R2R1" },
      { "from": "R1", "to": "C3R1" }
    ])
  };

  var options = {
    nodes: {
      borderWidth: 1,
      borderWidthSelected: 1,
      shape: "box",
      color: {
        border: 'lightgray',
        background: 'white',
        highlight: {
          border: 'lightgray',
          background: 'lightblue'
        },
        hover: {
          border: 'lightgray',
          background: 'lightblue'
        }
      }
    },
    edges: {
      smooth: {
        type: 'cubicBezier',
        forceDirection: 'vertical',
        roundness: 1
      },
      color: 'lightgray'
    },
    layout: {
      hierarchical: {
        direction: 'UD',
        nodeSpacing: 150
      }
    },
    interaction: {
      dragNodes: true
    },
    physics: false,
    edgeMinimization: false,
    blockShifting: false
  };
  var network = new vis.Network(document.getElementById("network"), graph, options);
}
#network {
  width: 100%;
  height: 180px;
}
<head>
  <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/vis/4.16.1/vis.min.js"></script>
  <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/vis/4.16.1/vis.min.css" />
</head>

<body onload="main();">
  <div id="network"></div>
</body>

The main bit is:

var nodes = new vis.DataSet([
    {"id": "M1", "label": "M1", "level": 0},
    {"id": "R1", "label": "R1", "level": 0},
    {"id": "W1", "label": "W1", "level": 0}, 

    {"id": "C1R1", "label": "C1R1", "level": 1},

    {"id": "C2R1", "label": "C2R1", "level": 1},
    {"id": "R2R1", "label": "R2R1", "level": 1},
    {"id": "W2R1", "label": "W2R1", "level": 1},
    {"id": "C3R1", "label": "C3R1", "level": 1}                      

]);

It's a family tree so I want that husband, wife and marriage node stay together.

This is what I am getting:

This is what I am looking for:

Basically on X axis, nodes should be shown in same order as they are inserted (thus no crossing or overlapping).

I have tried by keeping edge minimization as false, blockShifting as false. Tried even by giving x position, but it will still adjust itself.

Do let me know if there is any way to get it or there is no way.


回答1:


I finally decided to solve it by calculating positions of each node and fixing it.

Decide shape and corresponding size, spacing required by each node.

Level is already defined so that will give you 'y' co-ordinate of each node.

And for 'x' co-ordinate, say each node require space of 30 px and you want to keep margin of 5px on each side, so total 40 px.

At each level, for each node, you calculate how much x space (width) is required to draw all its child node and go on recursively.

In above example, R1 would need 200 (40*5) px width for x, so M1 and W1 can be drawn after or before that only. R1 can be drawn at center of 200 px width and we can get positions for C1R1, C2R1,R2R2, W2R1 and C3R1 by utilizing 40px for each.

If we start drawing at let's say: -200, 0

Then

M1 =>  x : -180, y : 0 (occupying space from -200 to -160)
R1 =>  x : -60, y : 0 (occupying space from -160 to 40)
W1 =>  x : 60, y: 0 (occupying space from 40 to 80)

C1R1 => -140, y: 40 (occupying space from -160 to -120)
C2R1 => -100, y: 40 (occupying space from -120 to -80)
R2R2 => -60, y: 40 (occupying space from -80 to -40)
W2R1 => -20, y: 40 (occupying space from -40 to 0)
C3R1 => 20, y: 40 (occupying space from 0 to 40)

Let me know if you want me to write exact code. It was very different for me, as I had different sizes of node and some other relationships etc



来源:https://stackoverflow.com/questions/49521382/hierarchical-layout-nodes-not-created-as-per-insertion-order-in-same-level

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!