我有一个D3 v4力模拟,节点在屏幕上移动。每个节点都是一个由圆圈和下面的一些文本组成的组。如何订购,以便圆圈位于底层,顶层的文字始终。圆圈与圆圈重叠是可以的,但是圆圈在文本顶部重叠是不可能的。这就是我所拥有的。目前,位于另一个节点之前的节点圈将与该节点的文本重叠。
this.centerNode = this.d3Graph.selectAll(null)
.data(this.nodes.slice(10,20))
.enter()
.append("g")
this.centerNode.append("circle")
.attr("class", "backCircle")
.attr("r", 60)
.attr("fill", "red")
this.centerNode
.append("text")
.attr("fill", "black")
.attr("font-size", "20px")
.attr("y", -60)
.text("test text" )
答案 0 :(得分:4)
使用您当前的方法无法达到预期的效果。原因很简单:每个组都有一个文本和一个圆圈。但是,绘画顺序取决于组的顺序:
<g>
<circle></circle>
<text></text><!-- this text here... -->
</g>
<g>
<circle></circle><!-- ...will be behind this circle here -->
<text></text>
</g>
<!-- etc... -->
因此,将文本和圆圈分组到<g>
元素中,您将按给定顺序绘制组,因此,在文本上绘制一个圆圈(给定组的圆圈绘制在文本上在它之前的所有小组)。
以下是演示文稿(Baz
圈子将位于所有文字的顶部,Bar
圈子将位于Foo
文字的顶部):
var width = 300;
var height = 200;
var svg = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height);
var nodes = [{
name: "Foo"
}, {
name: "Bar"
}, {
name: "Baz"
}];
var links = [{
"source": 0,
"target": 1
}, {
"source": 0,
"target": 2
}];
var simulation = d3.forceSimulation()
.force("link", d3.forceLink())
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(width / 2, height / 2));
var link = svg.selectAll(null)
.data(links)
.enter()
.append("line")
.style("stroke", "#ccc")
.style("stroke-width", 1);
var color = d3.scaleOrdinal(d3.schemeCategory20);
var node = svg.selectAll(null)
.data(nodes)
.enter()
.append("g")
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
var nodeCircle = node.append("circle")
.attr("r", 20)
.attr("stroke", "gray")
.attr("stroke-width", "2px")
.attr("fill", function(d, i) {
return color(i)
});
var nodeTexts = node.append("text")
.style("fill", "black")
.attr("dx", 20)
.attr("dy", 8)
.text(function(d) {
return d.name;
});
simulation.nodes(nodes);
simulation.force("link")
.links(links);
simulation.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.attr("transform", (d) => "translate(" + d.x + "," + d.y + ")")
});
function dragstarted(d) {
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}
function dragged(d) {
d.fx = d3.event.x;
d.fy = d3.event.y;
}
function dragended(d) {
if (!d3.event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
一种可能的解决方案是创建两个选项,一个用于圆圈,另一个用于文本。在之前添加圈子,在之后添加文本。请记住对两者使用相同的nodes
数组:
var node = svg.selectAll(null)
.data(nodes)
.enter()
.append("circle")
//etc...
var nodeTexts = svg.selectAll(null)
.data(nodes)
.enter()
.append("text")
//etc...
这样,文本将在圈子之上始终。
查看演示:
var width = 300;
var height = 200;
var svg = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height);
var nodes = [{
name: "Foo"
}, {
name: "Bar"
}, {
name: "Baz"
}];
var links = [{
"source": 0,
"target": 1
}, {
"source": 0,
"target": 2
}];
var simulation = d3.forceSimulation()
.force("link", d3.forceLink())
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(width / 2, height / 2));
var link = svg.selectAll(null)
.data(links)
.enter()
.append("line")
.style("stroke", "#ccc")
.style("stroke-width", 1);
var color = d3.scaleOrdinal(d3.schemeCategory20);
var node = svg.selectAll(null)
.data(nodes)
.enter()
.append("circle")
.attr("r", 20)
.attr("stroke", "gray")
.attr("stroke-width", "2px")
.attr("fill", function(d, i) {
return color(i)
})
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
var nodeTexts = svg.selectAll(null)
.data(nodes)
.enter()
.append("text")
.style("fill", "black")
.attr("dx", 20)
.attr("dy", 8)
.text(function(d) {
return d.name;
});
simulation.nodes(nodes);
simulation.force("link")
.links(links);
simulation.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.attr("transform", (d) => "translate(" + d.x + "," + d.y + ")")
nodeTexts.attr("transform", (d) => "translate(" + d.x + "," + d.y + ")")
});
function dragstarted(d) {
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}
function dragged(d) {
d.fx = d3.event.x;
d.fy = d3.event.y;
}
function dragended(d) {
if (!d3.event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}
<script src="https://d3js.org/d3.v4.min.js"></script>