d3强制有向图在svg上移动,分成一组节点

时间:2016-01-21 08:27:14

标签: javascript d3.js svg

我的力导向图是正确绘制的。但它并没有停留。我在svg上稍微移动,有时一些节点从可见性中消失,在这里和那里留下节点簇。这是图表最初的外观:

一段时间之后它看起来像这样:节点已远离div

var graph = new Object();
var map = new Object();
var index = 0;

var linkIndex = 0;

var width = $("#d3graph").width();
var height = $("#d3graph").height() ;


var svg = d3.select("#d3graph").append("svg:svg")
        .attr("width", width)
        .attr("height", height);

// tool tip with the label
var tip = d3.tip()
      .attr('class', 'd3-tip')
      .offset([-10, 0])
      .html(function (d) {
          return d.name + "";
      })
svg.call(tip);

/* I take nodes and edges from outside. That part works fine*/

graph.links = dataset2;
graph.nodes = dataset1;

function drapGraph(graph) {

    svg.selectAll("g.link").remove();
    svg.selectAll("g.gnode").remove();

    var  force = self.force = d3.layout.force()
            .nodes(graph.nodes)
            .links(graph.links)
            .gravity(.05)
            .distance(30)
            .charge(-120)
            .size([width, height])
            .start();

    //map radius  domain--> range
    var rScale = d3.scale.linear()
          .domain([d3.min(graph.nodes, function (d) {
              return Math.log(d.group);
          }), d3.max(graph.nodes, function (d) {
              return Math.log(d.group);
          })])
          .range([0, 30]);

    var link = svg.selectAll(".link")
          .data(graph.links)
          .enter().append("line")
          .attr("class", "link")
          .style("stroke-width", 2)
          .style("stroke-length", function (d) {return (10000/d.value);});

    var node = svg.selectAll("g.gnode")
          .data(graph.nodes)
          .enter().append("g")
          .attr("class", "gnode")
          .on('mouseover', tip.show)
          .on('mouseout', tip.hide)
          .call(force.drag);

    var maxretweets = d3.max(graph.nodes, function (d) {
        return Math.log(d.group);
    });
    var minretweets = d3.min(graph.nodes, function (d) {
        return Math.log(d.group);
    });
    var maxContent = d3.max(graph.nodes, function (d) {
        return d.degree;
    });
    var minvalue = d3.min(graph.links, function (d) {
        return d.value;
    });

    var circle = node.append("circle")
           .attr("r", function (d) {
               return rScale(Math.log(d.group));
           })
           .style("fill", function (d) {
               return d.color;

           })
            .style("stroke", "#000000")
           .on('mouseover', tip.show)
           .on('mouseout', tip.hide)
           .call(force.drag);

    //give you nodes with labels
    var label = node.append("text")
            .style("font-family", "sans-serif")
            .style("text-anchor", "middle")
            .style("font-size", "8")
            .style("stroke", "#404040")
            .text(function (d) {
                if (rScale(Math.log(d.group)) > 5) {
                   return d.name;
                }
            });



    force.on("tick", function () {

        node.attr("cx", function (d) {
            return d.x;
        })
        .attr("cy", function (d) {
            return d.y;
        });

        circle.attr("cx", function (d) {
            return d.x;
        })
        .attr("cy", function (d) {
            return d.y;
        });

        label.attr("x", function (d) {
            return d.x;
        })
        .attr("y", function (d) {
            return 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;
        });
    });

    svg.selectAll("g").attr("x", function (d) {
                                    return d.x;
                             })
                      .attr("y", function (d) {
                                 return d.y;
                                });
}

有人可以帮我解决这个问题吗?这里有一个小问题,但我无法弄明白,我尝试了很多东西,但它仍然无效。

1 个答案:

答案 0 :(得分:0)

我建议使用有界xy值来解决此类问题。

尝试计算刻度函数中的xy位置,如下所示。

 node.attr("cx", function(d) { return d.x = Math.max(radius, Math.min(width - radius, d.x)); })
     .attr("cy", function(d) { return d.y = Math.max(radius, Math.min(height - radius, d.y)); });

请参阅here以获取样本。

修改:无需单独更新圆圈和文字位置,因为它们已分组。只需更新组元素和链接如下。

force.on("tick", function () {
    svg.selectAll("g.node")
       .attr("transform", function (d) {
             d.x = Math.max(radius, Math.min(width - radius, d.x));
             d.y = Math.max(radius, Math.min(height - radius, d.y));
             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;
        });
    });   
}