-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnew_tree.html
245 lines (211 loc) · 7.15 KB
/
new_tree.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
<!DOCTYPE html>
<meta charset="UTF-8">
<style>
.node circle {
fill: #fff;
stroke: steelblue;
stroke-width: 3px;
}
.node text {
font: 12px sans-serif;
}
.link {
fill: none;
stroke: #ccc;
stroke-width: 2px;
}
</style>
<body>
<!-- load the d3.js library -->
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
// 设置图表的宽高和Margin
var margin = { top: 20, right: 90, bottom: 30, left: 90 },
width = 2000 - margin.left - margin.right,
height = 4000 - margin.top - margin.bottom;
var svg = d3
.select("body")
// 在页面的body里添加svg对象
.append("svg")
// 设置svg宽高
.attr("width", width + margin.right + margin.left)
.attr("height", height + margin.top + margin.bottom)
// 在svg里添加group元素
.append("g")
// 将group放置在左上方
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var i = 0,
duration = 750,
treeData,
root;
// 定义Tree层级,并设置宽高
var treemap = d3.tree().size([height, width]);
d3.json("nested_tree2.json", function(error, data) {
treeData = data;
// 计算父节点、子节点、高度和深度(parent, children, height, depth)
root = d3.hierarchy(treeData, function(d) {
return d.children;
});
// 设置第一个元素的初始位置
root.x0 = height / 2;
root.y0 = 0;
// 更新节点状态
update(root);
// collapse方法,用于切换子节点的展开和收起状态
function collapse(d) {
if (d.children) {
d._children = d.children;
d._children.forEach(collapse);
d.children = null;
}
}
function update(source) {
// 设置节点的x、y位置信息
var treeData = treemap(root);
// 计算新的Tree层级
var nodes = treeData.descendants(),
links = treeData.descendants().slice(1);
// 设置每个同级节点间的y间距为180
nodes.forEach(function(d) {
d.y = d.depth * 180;
});
// ****************** 节点部分操作 ***************************
// 给节点添加id,用于选择集索引
var node = svg.selectAll("g.node").data(nodes, function(d) {
return d.id || (d.id = ++i);
});
// 添加enter操作,添加类名为node的group元素
var nodeEnter = node
.enter()
.append("g")
.attr("class", "node")
// 默认位置为当前父节点的位置
.attr("transform", function(d) {
return "translate(" + source.y0 + "," + source.x0 + ")";
})
// 给每个新加的节点绑定click事件
.on("click", click);
// 给每个新加的group元素添加cycle元素
nodeEnter
.append("circle")
.attr("class", "node")
.attr("r", 1e-6)
// 如果元素有子节点,且为收起状态,则填充浅蓝色
.style("fill", function(d) {
return d._children ? "lightsteelblue" : "#fff";
})
.style("stroke", function(d) {
return d.data.type=="机构" ? "steelblue" : "green";
});
// 给每个新加的group元素添加文字说明
nodeEnter
.append("text")
.attr("dy", ".35em")
.attr("x", function(d) {
return d.children || d._children ? -13 : 13;
})
.attr("text-anchor", function(d) {
return d.children || d._children ? "end" : "start";
})
.text(function(d) {
return d.data.name;
});
// 获取update集
var nodeUpdate = nodeEnter.merge(node);
// 设置节点的位置变化,添加过渡动画效果
nodeUpdate
.transition()
.duration(duration)
.attr("transform", function(d) {
return "translate(" + d.y + "," + d.x + ")";
});
// 更新节点的属性和样式
nodeUpdate
.select("circle.node")
.attr("r", 5)
.style("fill", function(d) {
return d._children ? "lightsteelblue" : "#fff";
})
.style("stroke", function(d) {
return d.data.type=="机构" ? "steelblue" : "green";
})
.attr("cursor", "pointer");
// 获取exit操作
var nodeExit = node
.exit()
// 添加过渡动画
.transition()
.duration(duration)
.attr("transform", function(d) {
return "translate(" + source.y + "," + source.x + ")";
})
// 移除元素
.remove();
// exit集中节点的cycle元素尺寸变为0
nodeExit.select("circle").attr("r", 1e-6);
// exit集中节点的text元素可见度降为0
nodeExit.select("text").style("fill-opacity", 1e-6);
// ****************** 连接线部分操作 ***************************
// 更新数据
var link = svg.selectAll("path.link").data(links, function(d) {
return d.id;
});
// 添加enter操作,添加类名为link的path元素
var linkEnter = link
.enter()
.insert("path", "g")
.attr("class", "link")
// 默认位置为当前父节点的位置
.attr("d", function(d) {
var o = { x: source.x0, y: source.y0 };
return diagonal(o, o);
});
// 获取update集
var linkUpdate = linkEnter.merge(link);
// 更新添加过渡动画
linkUpdate
.transition()
.duration(duration)
.attr("d", function(d) {
return diagonal(d, d.parent);
});
// 获取exit集
var linkExit = link
.exit()
// 设置过渡动画
.transition()
.duration(duration)
.attr("d", function(d) {
var o = { x: source.x, y: source.y };
return diagonal(o, o);
})
// 移除link
.remove();
// 为动画过渡保存旧的位置
nodes.forEach(function(d) {
d.x0 = d.x;
d.y0 = d.y;
});
// 添加贝塞尔曲线的path,衔接与父节点和子节点间
function diagonal(s, d) {
path = `M ${s.y} ${s.x}
C ${(s.y + d.y) / 2} ${s.x},
${(s.y + d.y) / 2} ${d.x},
${d.y} ${d.x}`;
return path;
}
// 当点击时,切换children,同时用_children来保存原子节点信息
function click(d) {
if (d.children) {
d._children = d.children;
d.children = null;
} else {
d.children = d._children;
d._children = null;
}
update(d);
}
}
});
</script>
</body>