javascript - 3d.js - 更新力导向图上的节点

标签 javascript 3d force-layout

我目前正在开发一个程序来创建图形(顶点+边)并应用算法。我选择了 3d.js 来制作这个程序。 添加顶点时,我遇到了有关repaint函数的问题。

当我添加第一个顶点时,它可以工作,但是对于接下来的,我的顶点会快速倍增(顶点和标签)...

截图:

<小时/>

enter image description here
enter image description here

源代码:

<小时/>

var graph = (function() {
  return {
    modules: {},
    nodes: [],
    links: []
  }
})();

graph.modules.engin = (function() {
  var w, h, circleWidth, svgApp, force, link, node, nodes;
  var palette = {
    "white": "#FFFFFF",
    "gray": "#708284",
    "orange": "#BD3613",
    "red": "#D11C24",
    "blue": "#2176C7"
  };
  return {
    init: function() {
      var w = 960,
        h = 450;

      circleWidth = 7;

      svgApp = d3.select("body")
        .append("svg:svg")
        .attr("width", w)
        .attr("height", h)
        .attr("id", "svg")
        .attr("pointer-events", "all")
        .attr("viewBox", "0 0 " + w + " " + h)
        .attr("perserveAspectRatio", "xMinYMid")
        .append('svg:g');

      force = d3.layout.force()
        .nodes(graph.nodes)
        .links([])
        .gravity(0.1)
        .charge(-1000)
        .size([w, h]);


      //console.log(nodes);
      //nodes.push({})
      graph.modules.engin.repaint();

      graph.modules.engin.insertNode('V1');
      graph.modules.engin.insertNode('V2');
      graph.modules.engin.insertNode('V3');
    },
    repaint: function() {
      console.log('update');

      nodes = force.nodes();
      var links = force.links();

      link = svgApp.selectAll(".link")
        .data(links);
      link.enter().append("line")
        .attr("class", "link")
        .attr("stroke", palette.gray)
        .attr("fill", "none");
      link.exit().remove();


      node = svgApp.selectAll("circle.node")
        .data(nodes);
      node.enter().append("g")
        .attr("class", "node")
        .on("mouseover", function(d, i) { //MOUSEOVER
          if (!d.root) {
            d3.select(this).selectAll("circle")
              .transition()
              .duration(250)
              .style("cursor", "none")
              .attr("r", circleWidth + 3)
              .attr("fill", palette.orange);

            d3.select(this).select("text")
              .transition()
              .style("cursor", "none")
              .duration(250)
              .style("cursor", "none")
              .attr("font-size", "1.5em")
              .attr("x", 15)
              .attr("y", 5)
          } else {
            d3.select(this).selectAll("circle")
              .style("cursor", "none");

            d3.select(this).select("text")
              .style("cursor", "none");
          }
        })
        .on("mouseout", function(d, i) { //MOUSEOUT
          if (!d.root) {
            //CIRCLE
            d3.select(this).selectAll("circle")
              .transition()
              .duration(250)
              .attr("r", circleWidth)
              .attr("fill", palette.blue);

            //TEXT
            d3.select(this).select("text")
              .transition()
              .duration(250)
              .attr("font-size", "1em")
              .attr("x", 8)
              .attr("y", 4)
          }
        })
        .call(force.drag);

      node.append("svg:circle")
        .attr("cx", function(d) {
          return d.x;
        })
        .attr("cy", function(d) {
          return d.y;
        })
        .attr("r", circleWidth)
        .attr("fill", function(d, i) {
          if (!d.root) {
            return palette.blue;
          } else {
            return palette.red
          }
        });

      node.append("text")
        .text(function(d, i) {
          return d.name;
        })
        .attr("x", function(d, i) {
          return circleWidth + 5;
        })
        .attr("y", function(d, i) {
          if (!d.root) {
            return circleWidth
          } else {
            return circleWidth + 5
          }
        })
        .attr("font-family", "Bree Serif")
        .attr("fill", function(d, i) {
          return palette.white;
        })
        .attr("font-size", function(d, i) {
          return "1em";
        })
        .attr("text-anchor", function(d, i) {
          if (!d.root) {
            return "beginning";
          } else {
            return "end"
          }
        });
      node.exit().remove();

      force.on("tick", function(e) {
        node.attr("transform", function(d, i) {
          return "translate(" + d.x + "," + d.y + ")";
        });

        link.attr("x1", function(d) {
            return d.source.x;
          })
          .attr("y1", function(d) {
            return d.source.y;
          })
          .attr("x2", function(d) {
            return d.target.x;
          })
          .attr("y2", function(d) {
            return d.target.y;
          })
      });

      force.start();
    },
    insertNode: function(name) {
      nodes.push({
        name: name
      })
      graph.modules.engin.repaint();
    }
  }
})();
$(document).ready(function() {
  graph.modules.engin.init();
});
html {
  background-color: #042029;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>

<button onclick="addNodes()">Restart Animation</button>

谢谢你, 嗯嗯

最佳答案

我解决了我的问题:变量引用错误和选择器元素:

源代码:

var graph = (function() {
  return {
    modules: {},
    nodes: [],
    links: []
  }
})();

graph.modules.engin = (function() {
  var w, h, circleWidth, svgApp, force;
  var palette = {
    "white": "#FFFFFF",
    "gray": "#708284",
    "orange": "#BD3613",
    "red": "#D11C24",
    "blue": "#2176C7"
  };
  return {
    init: function() {
      h = $('body').height();
      w = $('body').width();

      circleWidth = 7;

      svgApp = d3.select("body")
        .append("svg:svg")
        .attr("pointer-events", "all")
        .attr("width", w)
        .attr("height", h)
        .attr("viewBox", "0 0 " + w + " " + h)
        .attr("perserveAspectRatio", "xMinYMid");

      force = d3.layout.force();

      graph.nodes = force.nodes();
      graph.links = force.links();

      graph.modules.engin.repaint();

      graph.modules.engin.insertNode('V1');
      graph.modules.engin.insertNode('V2');
      graph.modules.engin.insertNode('V3');
    },
    repaint: function() {
      console.log('update');

      var nodes = force.nodes();
      var links = force.links();

      console.log('BEFORE REPAINT');
      console.log(nodes);
      console.log(links);
      console.log(graph.nodes);
      console.log(graph.links);

      var link = svgApp.selectAll("line.link")
        .data(links);
      var linkEnter = link.enter().append("line")
        .attr("class", "link")
        .attr("stroke", palette.gray)
        .attr("fill", "none");
      link.exit().remove();


      var node = svgApp.selectAll("g.node")
        .data(nodes, function(d) {
          return d.name;
        });

      var nodeEnter = node.enter().append("g")
        .attr("class", "node")
        .on("mouseover", function(d, i) {
          if (!d.root) {
            d3.select(this).select("circle")
              .transition()
              .duration(250)
              .style("cursor", "none")
              .attr("r", circleWidth + 3)
              .attr("fill", palette.yellow);

            d3.select(this) //.select("text")
              .transition()
              .style("cursor", "none")
              .duration(250)
              .style("cursor", "none")
              .attr("font-size", "1.5em")
              .attr("x", 15)
              .attr("y", 5)
          } else {
            d3.select(this).select("circle")
              .style("cursor", "none");

            d3.select(this).select("text")
              .style("cursor", "none");

          }
        })
        .on("mouseout", function(d, i) {
          if (!d.root) {
            d3.select(this).select("circle")
              .transition()
              .duration(250)
              .attr("r", circleWidth)
              .attr("fill", palette.blue);

            d3.select(this) //.select("text")
              .transition()
              .duration(250)
              .attr("font-size", "1em")
              .attr("x", 8)
              .attr("y", 4)
          }
        })
        .call(force.drag);

      nodeEnter.append("svg:circle")
        .attr("cx", function(d) {
          return d.x;
        })
        .attr("cy", function(d) {
          return d.y;
        })
        .attr("r", circleWidth)
        .attr("fill", function(d, i) {
          if (!d.root) {
            return palette.blue;
          } else {
            return palette.red
          }
        }).attr("id", function(d) {
          return "Node-" + d.name;
        });

      nodeEnter.append("svg:text")
        .text(function(d, i) {
          return d.name;
        })
        .attr("x", function(d, i) {
          return circleWidth + 5;
        })
        .attr("y", function(d, i) {
          if (!d.root) {
            return circleWidth - 2
          } else {
            return circleWidth + 5
          }
        })
        .attr("font-family", "Bree Serif")
        .attr("fill", function(d, i) {
          return palette.white;
        })
        .attr("font-size", function(d, i) {
          return "1em";
        })
        .attr("text-anchor", function(d, i) {
          if (!d.root) {
            return "beginning";
          } else {
            return "end"
          }
        });

      node.exit().remove();

      force.on("tick", function(e) {
        node.attr("transform", function(d, i) {
          return "translate(" + d.x + "," + d.y + ")";
        });

        link.attr("x1", function(d) {
            return d.source.x;
          })
          .attr("y1", function(d) {
            return d.source.y;
          })
          .attr("x2", function(d) {
            return d.target.x;
          })
          .attr("y2", function(d) {
            return d.target.y;
          })
      });

      force.gravity(0.1)
        .charge(-1000)
        .size([w, h])
        .start();
    },
    insertNode: function(name) {
      graph.nodes.push({
        name: name
      })
      graph.modules.engin.repaint();
    }
  }
})();
$(document).ready(function() {
  graph.modules.engin.init();
});
html {
  background-color: #042029;
}

body {
  height: 600px;
  width: 100%;
}
<script src="https://d3js.org/d3.v3.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>

<button onclick="addNodes()">Restart Animation</button>

关于javascript - 3d.js - 更新力导向图上的节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37103969/

相关文章:

javascript - 使用 JsDoc3 创建 AngularJS 文档时出现问题

Javascript:获取 DOM 元素的 outerHTML *with* 值

c++ - 在给定 2D 图像点、深度图和相机校准矩阵的情况下提取 3D 坐标

d3.js - 在圆内添加图像 D3

javascript - 密码字段从密码中删除 '/' 字符

javascript - 从其他元素上的点击事件访问图像 src 属性

c++ - 如何确定边缘在 3d 中是凹的还是凸的?

javascript - 在 THREE.js 中使用四元数设置向量的全局旋转

javascript - D3径向力布置

javascript - D3js v5 中的有界静态力布局