在d3 v4中拖动带有标签的节点会强制布局毛刺

时间:2016-09-20 11:50:50

标签: d3.js

我是第一次在d3 v4尝试我的手的数据记者,以便创建一个力布局,使用Spotify API中的数据显示波段之间的关系。我首先按照Mike Bostock(https://bl.ocks.org/mbostock/4062045)发布的示例开始。我修改了代码,将每个svg圈元素包装在" g"元素:

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元素而不是组元素,但显然没有用。我也不确定最后一行是否真的在做任何有用的事情。

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和Moritz Stefaner的this one,但是还没有能够实施一个合适的解决方案(这两个都是d3 v3代码,据我所知,并没有多大帮助。

html页面的完整代码可在此pastebin中找到:http://pastebin.com/qw9bYHRD,如果需要进行某种测试,我可以使用{{{{{我在{{{{{ 3}}

对不起我对d3的了解不多,但这是我第一次深入了解图书馆(也是第一次使用v4)之后,使用了一些基于它的其他工具

非常感谢您的时间和精力。

1 个答案:

答案 0 :(得分: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));

从那时起它就能正常工作。您甚至可以只拖动标签,节点将在画布周围跟随它。太好了!