【问题标题】:Dragging nodes with labels in d3 v4 force layout glitches在 d3 v4 中拖动带有标签的节点强制布局故障
【发布时间】:2023-03-19 16:24:01
【问题描述】:

我是一名数据记者,第一次尝试使用 d3 v4,以便使用来自 Spotify API 的数据创建显示频段之间关系的强制布局。我从 Mike Bostock (https://bl.ocks.org/mbostock/4062045) 发布的示例开始。我修改了代码以将每个 svg circle 元素包装在一个“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() 函数以(希望)允许标签在节点被拖动时移动。您可以从我所做的评论中看到,我已经尝试将该方法应用于每个 circle 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 的,以及 Moritz Stefaner 的 this one,但还没有实现合适的解决方案(这两个都是 d3 v3 代码,据我所知知道,没有太大帮助)。

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

我很抱歉我对 d3 的了解很差,但这是我在使用基于它的其他一些工具一段时间后第一次深入了解该库(也是第一次使用 v4)。

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

【问题讨论】:

    标签: d3.js


    【解决方案1】:

    好吧,好像写了所有真正帮助我思考的东西,我自己设法解决了这个问题。在这里发布答案以防万一有人遇到同样的问题。

    非常简单的解决方案与执行.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));
    

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

    【讨论】:

      猜你喜欢
      • 2014-07-12
      • 1970-01-01
      • 1970-01-01
      • 2017-08-30
      • 1970-01-01
      • 1970-01-01
      • 2013-09-07
      • 1970-01-01
      • 2014-01-15
      相关资源
      最近更新 更多