在d3强制布局中移动固定节点

时间:2015-12-03 00:08:08

标签: javascript d3.js force-layout

我正在使用D3的强制布局来显示图形。现在,我要求节点在单击任何节点时更改其位置。

我查找了其他相关的StackOverflow问题,但这对我没有帮助。

渲染代码如下:

var render = function(graph){

       /* var loading = svg.append("text")
            .attr("x", width / 2)
            .attr("y", height / 2)
            .attr("dy", ".35em")
            .style("text-anchor", "middle")
            .text("Simulating. One moment please…");*/


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

        var link = svg.selectAll(".link")
            .data(graph.links);

        //Enter phase for links.
        link.enter().append("line");

        //Update phase for links
            link
            .attr("class", "link")
            .style("stroke-width", function(d) { return Math.sqrt(d.value); });

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

        //Enter phase for nodes
        var node_g = node.enter()
            .append("g")
            .attr("class","node")
            .on("dblclick",nodeClick)
            .call(force.drag);

        //Update phase for nodes

        node_g.append("text")
            .attr("class","NodeLabel")
            .text(function(d){
                return d.name;
            });

         var nodeCirlce = node_g.append("circle");

        nodeCirlce
            .attr("r", 5)
            .style("fill", function(d) { return color(d.group); })

        node_g.append("title")
            .text(function(d) { return d.name; });

            force.on("tick", function() {
            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; });

                node_g.attr("transform",function(d){
                    return "translate("+ d.x+","+ d.y+")";
                });

            //TODO : Add attr change for node text as well.
        });

节点点击处理程序的代码如下所示:

var nodeClick = function(d,i){
        //Translate the graph to center around the selected node.
        var x_trans = x_cent - d.x;
        var y_trans = y_cent - d.y;
        var nodes = oldGraph.nodes;

        for(var i=0;i<nodes.length;i++){
            var node = nodes[i];
            node.x = node.x + 1000;
            node.y = node.y + 1000;
            node.fixed = true;
        }
        //oldGraph.nodes = updateNodes(nodes,oldGraph.links);
        render(oldGraph);
        //setTimeout(function(){layout("json/HUMAN-1g.json");},000);

    };

但是,节点位置不会更新。

1 个答案:

答案 0 :(得分:1)

更改数据后,您需要运行更新DOM中位置的代码。这正是tick事件处理函数中的内容:

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; });

node_g.attr("transform",function(d){
                return "translate("+ d.x+","+ d.y+")";

我建议将其拉出到一个单独的函数中,然后将其设置为tick处理函数并从nodeClick()函数调用它。要清楚,需要从render()函数调用nodeClick()