Cytoscape.js - 为什么旧的 graphs/instances 在以编程方式添加新实例时消失?

Cytoscape.js - why do old graphs/instances disappear when new instances are added programmatically?

我创建了 "multiple instances" 示例 (https://js.cytoscape.org/demos/310dca83ba6970812dd0/) 的一个变体,其中不是在开头添加所有实例,而是一个新的 DIV 容器和一个 cytoscape 实例每次点击文档添加:


<!DOCTYPE html>

<html>
  <head>
    <meta charset=utf-8 />
    <meta name="viewport" content="user-scalable=no, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, minimal-ui">
    <title>Multiple instances</title>
    <script src="https://js.cytoscape.org/js/cytoscape.min.js"></script>
  </head>
  <body>
    <script>
      var elesJson = {
      nodes: [
          { data: { id: 'a', foo: 3, bar: 5, baz: 7 } },
          { data: { id: 'b', foo: 7, bar: 1, baz: 3 } },
          { data: { id: 'c', foo: 2, bar: 7, baz: 6 } },
          { data: { id: 'd', foo: 9, bar: 5, baz: 2 } },
          { data: { id: 'e', foo: 2, bar: 4, baz: 5 } }
      ],

      edges: [
          { data: { id: 'ae', weight: 1, source: 'a', target: 'e' } },
          { data: { id: 'ab', weight: 3, source: 'a', target: 'b' } },
          { data: { id: 'be', weight: 4, source: 'b', target: 'e' } },
          { data: { id: 'bc', weight: 5, source: 'b', target: 'c' } },
          { data: { id: 'ce', weight: 6, source: 'c', target: 'e' } },
          { data: { id: 'cd', weight: 2, source: 'c', target: 'd' } },
          { data: { id: 'de', weight: 7, source: 'd', target: 'e' } }
      ]
      };

      var count = 1;

      // add new container and cytoscape instance
      document.onclick = function () {

          var t = (count - 1) * 20;

          // first, add the container
          document.body.innerHTML += `<div id="cy${count}" style="position: absolute; left: 0; top: ${t}%; width: 100%; height: 20%; z-index: 999;"></div>`

          // then, add the cytoscape instance
          cytoscape({
          container: document.getElementById(`cy${count}`),
          style: cytoscape.stylesheet()
          .selector('node')
          .css({
              'background-color': '#B3767E',
              'width': 'mapData(baz, 0, 10, 10, 40)',
              'height': 'mapData(baz, 0, 10, 10, 40)',
              'content': 'data(id)'
          })
          .selector('edge')
          .css({
              'line-color': '#F2B1BA',
              'target-arrow-color': '#F2B1BA',
              'width': 2,
              'target-arrow-shape': 'circle',
              'opacity': 0.8
          })
          .selector(':selected')
          .css({
              'background-color': 'black',
              'line-color': 'black',
              'target-arrow-color': 'black',
              'source-arrow-color': 'black',
              'opacity': 1
          })
          .selector('.faded')
          .css({
              'opacity': 0.25,
              'text-opacity': 0
          }),

          elements: elesJson,

          layout: {
          name: 'circle',
          padding: 10
          },

          ready: function(){
          // ready 1
          }
          });

          // increment
          count++;
      }

    </script>
  </body>
</html>

我的预期是新实例出现在旧实例下方,但事实并非如此。

相反,新实例出现在预期位置,而旧实例消失了。旧实例的容器保留在 DOM.

我无法完全找到对这种行为的解释,尤其是因为所有其他内容都与原始示例中的一样。我在这里做错了什么?

Cytoscape 实例仍然存在,但是这些实例所附加的 DOM 元素会被新元素替换,因为您更改了整个 body.innerHTML

所以,基本上,而不是

document.body.innerHTML += `<div id="cy${count}" style="position: absolute; left: 0; top: ${t}%; width: 100%; height: 20%; z-index: 999;"></div>`

你应该做

let newCytoscapeInstanceContainer = document.createElement('div');
newCytoscapeInstanceContainer.id = `cy${count}`;
newCytoscapeInstanceContainer.style.cssText = `position: absolute; left: 0; top: ${t}%; width: 100%; height: 20%; z-index: 999;`;
document.body.appendChild(newCytoscapeInstanceContainer);

或使用 cy.mount() 将每个以前的 Cytoscape 实例绑定到新的 DOM 元素,但我不推荐。

工作笔 - https://codepen.io/Raven0us/pen/RwraGgB