I would like move the g element include multiple tspan text to enter.
JavaScript
x
107
107
1
demo()
2
3
function demo() {
4
//subtitle("iptable filter")
5
// 2. 描画用のデータ準備
6
var width = 800
7
var height = 400
8
var data = {name:"AAAnBBB",children: [
9
{name: "CCCnDDD",children:[
10
{name:"EEEnFFF"}
11
]},
12
{name: "GGGnHHH",children:[
13
{name:"IIInJJJ"}
14
]},
15
{name: "KKKnLLL",children: [
16
{name: "MMMnNNN"}
17
]},
18
{name: "OOOnPPP",children:[
19
{name: "QQQnRRR"}
20
]}
21
]}
22
23
var root = d3.hierarchy(data);
24
25
var tree = d3.tree()
26
.size([height, width])
27
28
tree(root);
29
30
var margin = {left:80,top:20,right:20,bottom:20}
31
var svg = d3.select('body').append("svg")
32
.attr('width',width + margin.left + margin.right)
33
.attr('height',height + margin.top + margin.bottom)
34
35
var g = svg.append("g")
36
.attr("transform", `translate(${margin.left},${margin.top})`)
37
38
var link = g.selectAll(".link")
39
.data(root.descendants().slice(1))
40
.enter()
41
.append("path")
42
.attr("class", "link")
43
.attr("d", function(d) {
44
return "M" + d.y + "," + d.x +
45
"C" + (d.parent.y + 100) + "," + d.x +
46
" " + (d.parent.y + 100) + "," + d.parent.x +
47
" " + d.parent.y + "," + d.parent.x;
48
});
49
50
var node = g.selectAll(".node")
51
.data(root.descendants())
52
.enter()
53
.append("g")
54
.attr("class", "node")
55
.attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; })
56
57
var txtnode = node.append("text")
58
.attr("text-anchor", 'start')
59
.attr("dominant-baseline","text-before-edge")//"middle"
60
.attr("font-size", "200%")
61
.selectAll('tspan')
62
.data(d => d.data.name.split('n'))
63
.join('tspan')
64
.attr('class','tspan')
65
.attr('x',0)
66
.attr('y',(d,i) => i*25)
67
.text(d => d)
68
69
node.each((d,i,n) =>{
70
var bbox = d3.select(n[i]).node().getBBox()
71
var margin = 4
72
bbox.x -= margin
73
bbox.y -= margin
74
bbox.width += 2*margin
75
bbox.height += 2*margin
76
d.bbox = bbox
77
})
78
79
node.insert("rect",'text')
80
.attr('fill','#FEFECE')
81
.attr('fill','none')
82
.attr('rx',5.5)
83
.attr('ry',5.5)
84
.attr('stroke','#A80036')
85
.attr('stroke-width',2)
86
.attr('x',d => d.bbox.x)
87
.attr('y',d => d.bbox.y)
88
.attr('width',d => d.bbox.width)
89
.attr('height',d => d.bbox.height)
90
91
node.attr('dx',(d,i,n) => {
92
var x = d.bbox.width/2
93
return -x
94
})
95
.attr('dy',(d,i,n) => {
96
var x = d.bbox.width/2
97
var y = d.bbox.height/2
98
return -y
99
})
100
101
g.selectAll('.link')
102
.attr('fill','none')
103
.attr('stroke','#555')
104
.attr('stroke-opacity',1)
105
.attr('stroke-width',4)
106
107
}
JavaScript
1
1
1
<script src="https://d3js.org/d3.v6.min.js"></script>
The attribute dx and dy doesn’t work in this example. what’s the proper way to move the g element to make it move to center?
Advertisement
Answer
For repositioning them dynamically, an easy approach is getting the size of the element and translating it up/left by half its height/width:
JavaScript
1
5
1
node.each(function(d) {
2
const thisSize = this.getBoundingClientRect();
3
d3.select(this).attr("transform", `translate(${d.y - thisSize.width/2},${d.x - thisSize.height/2})`)
4
});
5
Here is your code with that change:
JavaScript
1
130
130
1
demo()
2
3
function demo() {
4
//subtitle("iptable filter")
5
// 2. 描画用のデータ準備
6
var width = 800
7
var height = 400
8
var data = {
9
name: "AAAnBBB",
10
children: [{
11
name: "CCCnDDD",
12
children: [{
13
name: "EEEnFFF"
14
}]
15
},
16
{
17
name: "GGGnHHH",
18
children: [{
19
name: "IIInJJJ"
20
}]
21
},
22
{
23
name: "KKKnLLL",
24
children: [{
25
name: "MMMnNNN"
26
}]
27
},
28
{
29
name: "OOOnPPP",
30
children: [{
31
name: "QQQnRRR"
32
}]
33
}
34
]
35
}
36
37
var root = d3.hierarchy(data);
38
39
var tree = d3.tree()
40
.size([height, width])
41
42
tree(root);
43
44
var margin = {
45
left: 80,
46
top: 20,
47
right: 20,
48
bottom: 20
49
}
50
var svg = d3.select('body').append("svg")
51
.attr('width', width + margin.left + margin.right)
52
.attr('height', height + margin.top + margin.bottom)
53
54
var g = svg.append("g")
55
.attr("transform", `translate(${margin.left},${margin.top})`)
56
57
var link = g.selectAll(".link")
58
.data(root.descendants().slice(1))
59
.enter()
60
.append("path")
61
.attr("class", "link")
62
.attr("d", function(d) {
63
return "M" + d.y + "," + d.x +
64
"C" + (d.parent.y + 100) + "," + d.x +
65
" " + (d.parent.y + 100) + "," + d.parent.x +
66
" " + d.parent.y + "," + d.parent.x;
67
});
68
69
var node = g.selectAll(".node")
70
.data(root.descendants())
71
.enter()
72
.append("g")
73
.attr("class", "node");
74
75
var txtnode = node.append("text")
76
.attr("text-anchor", 'start')
77
.attr("dominant-baseline", "text-before-edge") //"middle"
78
.attr("font-size", "200%")
79
.selectAll('tspan')
80
.data(d => d.data.name.split('n'))
81
.join('tspan')
82
.attr('class', 'tspan')
83
.attr('x', 0)
84
.attr('y', (d, i) => i * 25)
85
.text(d => d)
86
87
node.each((d, i, n) => {
88
var bbox = d3.select(n[i]).node().getBBox()
89
var margin = 4
90
bbox.x -= margin
91
bbox.y -= margin
92
bbox.width += 2 * margin
93
bbox.height += 2 * margin
94
d.bbox = bbox
95
})
96
97
node.insert("rect", 'text')
98
.attr('fill', '#FEFECE')
99
.attr('fill', 'none')
100
.attr('rx', 5.5)
101
.attr('ry', 5.5)
102
.attr('stroke', '#A80036')
103
.attr('stroke-width', 2)
104
.attr('x', d => d.bbox.x)
105
.attr('y', d => d.bbox.y)
106
.attr('width', d => d.bbox.width)
107
.attr('height', d => d.bbox.height)
108
109
node.attr('dx', (d, i, n) => {
110
var x = d.bbox.width / 2
111
return -x
112
})
113
.attr('dy', (d, i, n) => {
114
var x = d.bbox.width / 2
115
var y = d.bbox.height / 2
116
return -y
117
})
118
119
g.selectAll('.link')
120
.attr('fill', 'none')
121
.attr('stroke', '#555')
122
.attr('stroke-opacity', 1)
123
.attr('stroke-width', 4)
124
125
node.each(function(d) {
126
const thisSize = this.getBoundingClientRect();
127
d3.select(this).attr("transform", `translate(${d.y - thisSize.width/2},${d.x - thisSize.height/2})`)
128
});
129
130
}
JavaScript
1
1
1
<script src="https://d3js.org/d3.v6.min.js"></script>