2016-09-20 85 views
3

我是第一次尝试使用d3 v4的数据记录员,以便使用来自Spotify API的数据创建显示band之间关系的force布局。我从Mike Bostock发布的例子开始(https://bl.ocks.org/mbostock/4062045)。我修改了代码,以每SVG圆形元素包裹一个“G”的元素:在d3 v4中拖拽带有标签的节点强制布局故障

var link = svg.append("g").attr("class", "links") 
      .selectAll("line") 
      .data(graph.links) 
      .enter().append("line") 
       .attr("stroke-width", function(d) { return Math.sqrt(d.value); }); 
var gnodes = svg.selectAll("g.gnode") 
      .data(graph.nodes) 
      .enter() 
      .append("g") 
      .classed("gnode", true); 
var node = gnodes.append("circle") 
      .attr("class", "nodes") 
      .attr("r", 5) 
      .style("fill", function(d) { return color(d.group); }) 
      .call(d3.drag() 
       .on("start", dragstarted) 
       .on("drag", dragged) 
       .on("end", dragended)); 

这样做之后,我创建的标题和标签元素,并将它们添加到节点:

gnodes.append("title").text(function(d) { return d.label }); 
var labels = gnodes.append("text").text(function(d) { return d.label; }); 
labels.attr("transform", function(d) { 
    return "translate(" + (d.x) + "," + (d.y) + ")"; 
}); 

最后,我修改了ticked()函数(有希望)允许标签在拖动节点时移动。你可以通过评论我看到,我已经尝试将该方法应用于每个svg元素而不是group元素,但显然不起作用。我也不确定最后一行是否真的在做有用的事情。

function ticked() { 
    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; }); 
    gnodes 
    //node 
     .attr("transform", function(d) { 
      return "translate(" + [d.x, d.y] + ")";}); 
    labels.attr("transform", function(d) { return "translate(" + (d.x) + "," + (d.y) + ")"; }); 
} 

的问题是,虽然标签得到正确显示,当一个节点被拖动的节点“故障”,不检点,很可能是因为标签以某种方式感到困惑什么的,他们是不移动“同步”,可以这么说。

我已经看过this example,也是Mike Bostock和this one Moritz Stefaner,但还没有能够实现一个合适的解决方案(这两个都是d3 v3代码,据我所知,didn帮助不大)。

该页面的完整代码位于此pastebin:http://pastebin.com/qw9bYHRD,如果需要进行某种测试,我用来生成网络图的JSON文件位于this address

对于我对d3的深入了解,我很遗憾,但是这是我第一次深入图书馆(也是第一次使用v4)之后,在使用其他一些工具之后使用了一段时间。

非常感谢您的时间和关注。

回答

2

好的,好像写了所有实际上帮助我思考的东西,并且我自己设法解决了这个问题。在这里发布答案,以防有人碰巧遇到同样的问题。

非常简单的解决方案与执行.call(d3.drag())的对象有关。我切这片从节点变量(circle SVG元素)码,并在该定义g SVG元素的变量的末尾粘贴它:

.call(d3.drag() 
    .on("start", dragstarted) 
    .on("drag", dragged) 
    .on("end", dragended)); 

所以g元素声明结束这样的:

var gnodes = svg.selectAll("g.gnode") 
    .data(graph.nodes) 
    .enter() 
    .append("g") 
    .classed("gnode", true) 
    .call(d3.drag() 
     .on("start", dragstarted) 
     .on("drag", dragged) 
     .on("end", dragended)); 

它从此工作正常。你甚至可以拖动标签,节点将沿着画布进行拖动。大!