d3.js의 노드 중앙에 레이블 배치
나는 d3.js로 시작하고 각각 중앙 번호 레이블을 포함하는 노드 행을 만들려고합니다.
원하는 결과를 시각적으로 생성 할 수는 있지만 각 텍스트 요소에 대한 xy 좌표를 하드 코딩해야하므로 내가 한 방식은 최적이 아닙니다. 다음은 코드입니다.
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;
});
node
클래스는 사용자 정의 CSS 클래스 I는 별도로 정의한입니다 circle
클래스 반면, 요소 nodes
와는 labels
명시 적으로 정의되지 않으며 그들은이에서 빌린 대답 .
보시다시피 각 텍스트 레이블의 위치는 하드 코딩되어 각 노드의 중앙에 나타납니다. 분명히 이것은 올바른 해결책이 아닙니다.
내 질문은 레이블의 위치가 원의 위치와 함께 자동으로 변경되도록 각 텍스트 레이블을 각 노드 원과 동적으로 올바르게 연결하는 방법입니다. 개념 설명은 코드 예제로 매우 환영합니다.
텍스트 앵커 D3에 의해 생성 된 SVG 요소에서 예상대로 속성이 작동합니다. 그러나 추가 할 필요가 text
와를 circle
공통으로 g
수 있도록 요소 text
와는 circle
서로를 중심으로한다.
이를 위해 nodes
변수를 다음과 같이 변경할 수 있습니다 .
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 + ")";
});
(가) 있습니다 dataset
있도록 개체의 목록이 지금 d.y
과 d.x
문자열 단지 목록 대신 사용할 수 있습니다.
그런 다음, 교체 circle
및 text
다음 추가 인 코드를 :
// 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;
});
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
.
Here is a JSFiddle showing centered text on circles.
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 + ")";
});
The best answer came from the asker himself:
just a further observation: with only .attr("text-anchor", "middle") for each text element, the label is at the middle horizontally but slightly off vertically. I fixed this by adding attr("y", ".3em") (borrowed from examples at d3.js website), which seems to work well even for arbitrary size of node circle. However, what exactly this additional attribute does eludes my understanding. Sure, it does something to the y-coordinate of each text element, but why .3em in particular? It seems almost magical to me...
Just add .attr("text-anchor", "middle")
to each text element.
Example:
node.append("text")
.attr("x", 0)
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.text(function(d) { return d.name; });
This page describes what's going on under the svg hood when it comes to text elements. Understanding the underlying machinery and data structures helped me get a better handle on how I had to modify my code to get it working.
ReferenceURL : https://stackoverflow.com/questions/11857615/placing-labels-at-the-center-of-nodes-in-d3-js
'programing' 카테고리의 다른 글
C # 스레드가 잠들지 않습니까? (0) | 2021.01.14 |
---|---|
행 복사하지만 새 ID 사용 (0) | 2021.01.14 |
ggplot2의 막대 그림에서 막대 사이의 공간을 늘리는 방법은 무엇입니까? (0) | 2021.01.14 |
Rails 및 Devise의 강력한 매개 변수 (0) | 2021.01.14 |
/ dir 및 / dir /과 같이 후행 슬래시가 있거나없는 .gitignore 규칙의 차이점 (0) | 2021.01.14 |