将标签放在d3.js中节点的中心 [英] Placing labels at the center of nodes in d3.js
问题描述
我从d3.js开始,我试图创建一行节点,每个节点都包含一个居中的数字标签。
I am starting with d3.js, and am trying to create a row of nodes each of which contains a centered number label.
我能够生成所需的结果在视觉上,但我做的方式是几乎不是最佳的,因为它涉及硬编码每个文本元素的xy坐标。下面是代码:
I am able to produce the desired result visually, but the way I did it is hardly optimal as it involves hard-coding the x-y coordinates for each text element. Below is the code:
var svg_w = 800;
var svg_h = 400;
var svg = d3.select("body")
.append("svg")
.attr("width", svg_w)
.attr("weight", svg_h);
var dataset = [];
for (var i = 0; i < 6; i++) {
var datum = 10 + Math.round(Math.random() * 20);
dataset.push(datum);
}
var nodes = svg.append("g")
.attr("class", "nodes")
.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("class", "node")
.attr("cx", function(d, i) {
return (i * 70) + 50;
})
.attr("cy", svg_h / 2)
.attr("r", 20);
var labels = svg.append("g")
.attr("class", "labels")
.selectAll("text")
.data(dataset)
.enter()
.append("text")
.attr("dx", function(d, i) {
return (i * 70) + 42
})
.attr("dy", svg_h / 2 + 5)
.text(function(d) {
return d;
});
节
类是自定义CSS类I分别为 circle
元素定义,而类 nodes
和标签
未明确定义,而是从此答案借用。
The node
class is custom CSS class I've defined separately for the circle
elements, whereas classes nodes
and labels
are not explicitly defined and they are borrowed from this answer.
如图所示,每个文本标签的位置是硬编码的,因此它出现在每个节点的中心。显然,这不是正确的解决方案。
As seen, the positioning of each text label is hard-coded so that it appears at the center of the each node. Obviously, this is not the right solution.
我的问题是,我应该如何正确地关联每个文本标签与每个节点圆动态,以便如果标签的位置更改以及一个圆的自动。
My question is that how should I correctly associate each text label with each node circle dynamically so that if the positioning of a label changes along with that of a circle automatically. Conceptual explanation is extremely welcome with code example.
推荐答案
text-anchor 属性在D3创建的svg元素上按预期工作。但是,您需要将文本
和圆
附加到公共 g
元素,以确保文本
和圆
彼此居中。
The text-anchor attribute works as expected on an svg element created by D3. However, you need to append the text
and the circle
into a common g
element to ensure that the text
and the circle
are centered with one another.
为此,您可以将节点
变量更改为:
To do this, you can change your nodes
variable to:
var nodes = svg.append("g")
.attr("class", "nodes")
.selectAll("circle")
.data(dataset)
.enter()
// Add one g element for each data node here.
.append("g")
// Position the g element like the circle element used to be.
.attr("transform", function(d, i) {
// Set d.x and d.y here so that other elements can use it. d is
// expected to be an object here.
d.x = i * 70 + 50,
d.y = svg_h / 2;
return "translate(" + d.x + "," + d.y + ")";
});
请注意,数据集
现在是一个列表的对象,以便可以使用 dy
和 dx
而不只是一个字符串列表。
Note that the dataset
is now a list of objects so that d.y
and d.x
can be used instead of just a list of strings.
然后,替换您的圈
和文本
p>
Then, replace your circle
and text
append code with the following:
// Add a circle element to the previously added g element.
nodes.append("circle")
.attr("class", "node")
.attr("r", 20);
// Add a text element to the previously added g element.
nodes.append("text")
.attr("text-anchor", "middle")
.text(function(d) {
return d.name;
});
现在,不是改变圆的位置
您更改 g
元素的位置,它会移动圆
和文本
。
Now, instead of changing the position of the circle
you change the position of the g
element which moves both the circle
and the text
.
以下是 JSFiddle
如果您希望将文本放在单独的 g
元素中,总是显示在顶部,然后使用第一个 g
。 dx
和 dy
/ code>元素的创建转换
If you want to have your text be in a separate g
element so that it always appears on top, then use the d.x
and d.y
values set in the first g
element's creation to transform
the text.
var text = svg.append("svg:g").selectAll("g")
.data(force.nodes())
.enter().append("svg:g");
text.append("svg:text")
.attr("text-anchor", "middle")
.text(function(d) { return d.name; });
text.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
这篇关于将标签放在d3.js中节点的中心的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!