d3文本不随节点移动

时间:2015-06-28 18:17:00

标签: javascript d3.js coffeescript

我尝试了一些方法,比如mbostock提出的d3 Node Labeling。但它不起作用,我的文本仍然不随节点移动,它们是静态的。

(使用CoffeeScript编码)

vis = d3.select(selection).append("svg")
  .attr("width", width)
  .attr("height", height)
linksG = vis.append("g").attr("class", "links")
nodesG = vis.append("g").attr("class", "nodes")
labelG = vis.append("g").attr("class", "labels")

nodeP = nodesG.selectAll("circle.node")
  .data(curNodesDataP)
nodeP.enter().append("circle")
  .attr("class", "node")
  .attr("r", 15)
  .style("fill", (d) -> nodeColors(d.id))
  .style("stroke", (d) -> strokeFor(d))
  .style("stroke-width", 1.0)
  .call(force.drag)

text = labelG.selectAll("text")
  .data(curNodesDataP)
text.enter().append("text")
    .attr("dx", 12)
    .attr("dy", ".35em")
    .text((d) -> d.id)

我困扰了好几天,我该怎么修呢?谢谢!

- zzcheng

1 个答案:

答案 0 :(得分:1)

您将链接,节点和标签附加到单独的g组中。因此,您应该在tick函数(链接组,节点组和标签组)中更新每个组的位置。

这是一个相同的小提琴。请注意,我也在tick函数中更新标签组的位置。



var w = 900,
    h = 400;

var circleWidth = 5;

var nodes = [{
    "name": "Matteo"
}, {
    "name": "Daniele"
}, {
    "name": "Marco"
}, {
    "name": "Lucio"
}, {
    "name": "Davide"
}];

var links = [{
    source: nodes[0],
    target: nodes[1]
}, {
    source: nodes[1],
    target: nodes[2]
}, {
    source: nodes[0],
    target: nodes[3]
}, {
    source: nodes[4],
    target: nodes[2]
}, {
    source: nodes[2],
    target: nodes[3]
}];



var vis = d3.select("body")
    .append("svg:svg")
    .attr("class", "stage")
    .attr("width", w)
    .attr("height", h);

var force = d3.layout.force()
    .nodes(nodes)
    .links([])
    .gravity(0.1)
    .charge(-1000)
    .size([w, h]);

var link = vis.selectAll(".link")
    .data(links)
    .enter().append("line")
    .attr("class", "link")
    .attr("stroke", "#CCC")
    .attr("fill", "none");

var node = vis.selectAll("circle.node")
    .data(nodes)
    .enter().append("g")
    .attr("class", "node")
    .call(force.drag);

var labels = vis.selectAll("text.label")
    .data(nodes)
    .enter().append("g")
    .attr("class", "label");   

//CIRCLE
node.append("svg:circle")
    .attr("cx", function(d) {
        return d.x;
    })
    .attr("cy", function(d) {
        return d.y;
    })
    .attr("r", circleWidth)
    .attr("fill", "pink");


//TEXT
labels.append("text")
    .text(function(d, i) {
        return d.name;
    })
    .attr("x", function(d, i) {
        return circleWidth + 5;
    })
    .attr("y", function(d, i) {
        if (i > 0) {
            return circleWidth + 0
        } else {
            return 8
        }
    })
    .attr("font-family", "Bree Serif")
    .attr("fill", "green")
    .attr("font-size", "1em")
    .attr("text-anchor", function(d, i) {
        if (i > 0) {
            return "beginning";
        } else {
            return "end"
        }
    })



force.on("tick", function(e) {
    node.attr("transform", function(d, i) {
        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;
        });
  
    labels.attr("transform", function(d, i) {
        return "translate(" + d.x + "," + d.y + ")";
    });
});

force.start();

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
&#13;
&#13;
&#13;

其他可能且更有效的方法是将节点和标签组合在一起。这是一个示例小提琴,其中节点和标签被分组,并且仅在tick函数中更新节点组和链接组的位置。

&#13;
&#13;
var w = 900,
    h = 400;

var circleWidth = 5;

var nodes = [{
    "name": "Matteo"
}, {
    "name": "Daniele"
}, {
    "name": "Marco"
}, {
    "name": "Lucio"
}, {
    "name": "Davide"
}];

var links = [{
    source: nodes[0],
    target: nodes[1]
}, {
    source: nodes[1],
    target: nodes[2]
}, {
    source: nodes[0],
    target: nodes[3]
}, {
    source: nodes[4],
    target: nodes[2]
}, {
    source: nodes[2],
    target: nodes[3]
}];



var vis = d3.select("body")
    .append("svg:svg")
    .attr("class", "stage")
    .attr("width", w)
    .attr("height", h);

var force = d3.layout.force()
    .nodes(nodes)
    .links([])
    .gravity(0.1)
    .charge(-1000)
    .size([w, h]);

var link = vis.selectAll(".link")
    .data(links)
    .enter().append("line")
    .attr("class", "link")
    .attr("stroke", "#CCC")
    .attr("fill", "none");

var node = vis.selectAll("circle.node")
    .data(nodes)
    .enter().append("g")
    .attr("class", "node")
    .call(force.drag);

//CIRCLE
node.append("svg:circle")
    .attr("cx", function(d) {
        return d.x;
    })
    .attr("cy", function(d) {
        return d.y;
    })
    .attr("r", circleWidth)
    .attr("fill", "pink");
//TEXT
node.append("text")
    .text(function(d, i) {
        return d.name;
    })
    .attr("x", function(d, i) {
        return circleWidth + 5;
    })
    .attr("y", function(d, i) {
        if (i > 0) {
            return circleWidth + 0
        } else {
            return 8
        }
    })
    .attr("font-family", "Bree Serif")
    .attr("fill", "green")
    .attr("font-size", "1em")
    .attr("text-anchor", function(d, i) {
        if (i > 0) {
            return "beginning";
        } else {
            return "end"
        }
    })



force.on("tick", function(e) {
    node.attr("transform", function(d, i) {
        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;
        })
});

force.start();
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
&#13;
&#13;
&#13;