当每个节点的子节点数大于 5 时,图形飞出屏幕

The graph fly out of screen when the child number per node is greater than 5

我学习了 cytoscape.js 和相关的扩展,并尝试了它的许多惊人的功能。

我发现当children的个数大于5,展开一个节点时,整个图飞出屏幕。

我构建了更复杂的数据,每个父节点拥有 3 个父节点和 5 个子节点。任意两个子节点之间存在连接。 所以有3个父节点,15个子节点和14+13+12..1个链接。

综上所述,当链接较多时,布局行为看起来不正常。

请看下面我的演示。

你可以修改我函数的参数getInitData()看看效果

document.addEventListener('DOMContentLoaded', function(){

    var cy = window.cy = cytoscape({
     container: document.getElementById('cy'),

     ready: function(){
      var api = this.expandCollapse({
       layoutBy: {
        name: "cose-bilkent",
        animate: 'end',
        randomize: false,
        fit: false,
        idealEdgeLength : 150
       },
       fisheye: false,
       animate: true,
       undoable: false
      });
      api.collapseAll();
     },

     style: [
      {
       selector: 'node',
       style: {
        'background-color': '#ad1a66'
       }
      },

      {
       selector: ':parent',
       style: {
        'background-opacity': 0.333
       }
      },

      {
       selector: "node.cy-expand-collapse-collapsed-node",
       style: {
        "background-color": "darkblue",
        "shape": "rectangle"
       }
      },

      {
       selector: 'edge',
       style: {
        'width': 3,
        'line-color': '#ad1a66'
       }
      },

      {
       selector: 'edge.meta',
       style: {
        'width': 2,
        'line-color': 'red'
       }
      },

      {
       selector: ':selected',
       style: {
         "border-width": 3,
        "border-color": '#DAA520'
       }
      }
     ],

     
     elements : getInitData(3, 5)
    });

    var api = cy.expandCollapse('get');
    var elements = null;

    

   });

   function getInitData(parentNum, childrenNum){
    var data = [], children = [], i, j, n;
    for(i = 0; i < parentNum; i++){
     n = "parent"+i;
     data.push({"group":'nodes',data:{"id":n}});
     for(j = 0; j < childrenNum; j++){
      children.push({"group":'nodes',data:{"id":n+"_child_"+j, parent:n}});
     }
    }
    
    var s,t;
    for(i = 0; i < children.length - 1; i++){
     s = children[i].data.id;
     for(j = i+1; j < children.length; j++){
      t = children[j].data.id;
      data.push({"group":'edges',data:{"id":s+"_"+t, source:s, target:t}});
     }
    }
    return data.concat(children);
   }
body {
  font-family: helvetica neue, helvetica, liberation sans, arial, sans-serif;
  font-size: 14px;
}

#cy {
  z-index: 999;
  width: 100%;
  height: 100%;
}

h1 {
  opacity: 0.5;
  font-size: 1em;
  font-weight: bold;
}
<script src="https://code.jquery.com/jquery-2.0.3.min.js"></script>
<script src="https://unpkg.com/cytoscape@3.1.0/dist/cytoscape.min.js"></script>

<!-- for testing with local version of cytoscape.js -->
<!--<script src="../cytoscape.js/build/cytoscape.js"></script>-->
<script src="https://unpkg.com/cytoscape-cose-bilkent@4.0.0/cytoscape-cose-bilkent.js"></script>
<script src="https://unpkg.com/cytoscape-expand-collapse@3.1.1/cytoscape-expand-collapse.js"></script>
<div id="cy"></div>

解决方法一:

您的图表没有任何拟合逻辑。您可以使用 cy.center(), which centers the graph to the current viewport and cy.fit() 这两种方法自行实现,这会将图形缩放到正确的位置。每次更改图形时都必须调用这些方法,例如当您添加一个节点时,删除一个节点,或者像您的情况一样展开和折叠。您可以通过绑定这些事件并在那里调用上述方法来实现。 绑定,正如你从上一个问题中了解到的那样:

cy.unbind('event');
cy.bind('event', 'target', function (event) {...});

方案二:

您也可以选择,如果可能(并非所有布局都可以这样做),将方法设置为 fit: true,,它在内部适合具有 cy.fit();cy.center(); 的图形。

其他问题和解决方案:

你说过,当你的图只有一个节点时看起来很糟糕,所以为了避免这种情况,你可以将 'cose-bilkent' 的填充 属性 设置为更大的数字。您可以在选项的初始化时执行此操作。

document.addEventListener('DOMContentLoaded', function() {
  var padding = 10;
  var cy = window.cy = cytoscape({
    container: document.getElementById('cy'),
    layout: {
      name: 'cose-bilkent',
      animate: false,
      randomize: true
    },
    style: [{
        selector: 'node',
        style: {
          'background-color': '#ad1a66'
        }
      },
      {
        selector: 'edge',
        style: {
          'width': 3,
          'line-color': '#ad1a66'
        }
      }
    ],
    elements: [{
      "data": {
        "id": "glyph9"
      }
    }]
  });
  document.getElementById("add").addEventListener("click", function() {
    padding += 10;
    var layout = cy.layout({
      name: 'cose-bilkent',
      animate: false,
      padding: padding
    });
    layout.run();
  });
});
body {
  font: 14px helvetica neue, helvetica, arial, sans-serif;
}

#cy {
  height: 90%;
  width: 100%;
  position: absolute;
  float: left;
}

button {
  margin-right: 10px;
}
<!DOCTYPE>

<html>

<head>
  <title>cytoscape-cose-bilkent.js demo</title>

  <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1">

  <script src="https://code.jquery.com/jquery-2.0.3.min.js"></script>
  <script src="https://unpkg.com/cytoscape@3.1.0/dist/cytoscape.min.js"></script>

  <!-- for testing with local version of cytoscape.js -->
  <!--<script src="../cytoscape.js/build/cytoscape.js"></script>-->
  <script src="https://unpkg.com/cytoscape-cose-bilkent@4.0.0/cytoscape-cose-bilkent.js"></script>
  <script src="https://unpkg.com/cytoscape-expand-collapse@3.1.1/cytoscape-expand-collapse.js"></script>

</head>

<body>

  <button id="add" type="button">Add padding</button>

  <div id="cy"></div>

</body>

</html>