d3文本没有't随节点移动

d3 text doesn't move with the nodes

本文关键字:节点 移动 文本 d3      更新时间:2023-09-26

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

(使用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

您将链接、节点和标签附加在单独的g组中。因此,您应该更新勾选功能中每个组的位置(链接组、节点组和标签组)。

这是一把同样的小提琴样品。请注意,我也在刻度函数中更新标签组的位置。

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>

其他可能且更有效的方法是将节点和标签分组在一起。这里有一个示例fiddle,其中节点和标签被分组,并且仅在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);
//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();
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>