-
Notifications
You must be signed in to change notification settings - Fork 0
/
学术家族树.html
343 lines (300 loc) · 13.4 KB
/
学术家族树.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
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1.0, user-scalable=no">
<link rel="stylesheet" href="bootstrap/css/bootstrap.min.css">
<title>学术家族树</title>
<link href="bootstrap/css/bootstrap.min.css" rel="stylesheet">
<script src="js/jquery.min.js"></script>
<script src="bootstrap/js/bootstrap.min.js"></script>
<link type="text/css" rel="stylesheet" href="type.css">
</head>
<body>
<script src="js/d3.v3.min.js"></script>
<div class="flex-container">
<p id="title">家族树</p>
<textarea type="textarea" id="text" cols="60" rows="10" class="center" placeholder="请输入内容"></textarea>
<button href="javascript:;" onclick="getdata()" class="button_left">建立家族树</button>
</div>
<!--使用onclick触发下面的方法-->
<script>
var treeData = [{
"name": "",
"parent": "",
"children": [{
"name": "",
"parent": "",
"children": [{
"name": "",
"parent": ""
}, {
"name": "",
"parent": "",
"children": [{
"name": "",
parent: ""
}]
}, {
"name": "",
"parent": ""
}, {
"name": "",
"parent": ""
}]
}, {
"name": "",
"parent": "",
"children": [{
"name": "",
"parent": ""
}, {
"name": "",
"parent": ""
}, ]
}, {
"name": "",
"parent": ""
}, ]
}];
function getdata() {
var text = $("#text").val(); //获取id为text的textarea的全部内容
var text1 = text.split("\n\n");//针对多组数据输入的情况,以“\n\n"为关键字进行分组,调用split函数进行分割
for (var k = 0; k < text1.length; k++) { //text1.length用于得到分组的数量
var arry = text1[k].split("\n");//针对每一组数据,以“\n"为关键字进行分组,得到每条导师和学生的信息
var teacher = {
name: '',
children: []
}
for (var ii = 0; ii < arry.length; ii++) {
var newarr = arry[ii].split(":");//针对每条导师和学生的信息,以“:”为关键字进行分组,可得到身份标签和身份信息
var type = [];
var type1 = [];
var a1 = newarr[0]; //获取身份标签,如导师、2016级博士生等,保存在a1变量
if (ii != 0) {
type1.name = a1;
}
var a2 = newarr[1];//获取身份信息,如天一、王二、吴五等,保存在a2变量
var a3 = a2.split("、");//针对每组身份信息,以“、”为关键字进行切分,得到每个人的名字信息
for (var j = 0; j < a3.length; j++) { //a3.length用于得到每条身份信息里名字的数量
var student = {};
if (ii == 0) {
teacher.name = a3[j];
}
if (ii != 0) {
student.name = a3[j];
type.push(student);
}
}
if (ii != 0) {
type1.children = type;
teacher.children.push(type1);
}
}
treeData[k] = [];
treeData[k] = teacher;
maketree(k);
}
}
function maketree(k) {
var margin = {
top: 20,
right: 120,
bottom: 20,
left: 550,
},
width = 960 - margin.right - margin.left ,
height = 500 - margin.top - margin.bottom ;
var i = 0,
duration = 750, //过渡延迟时间
root;
var tree = d3.layout.tree() //创建一个树布局
.size([height, width]);
var diagonal = d3.svg.diagonal()
.projection(function(d) {
return [d.y, d.x];
}); //创建新的斜线生成器
//声明与定义画布属性
var svg = d3.select("body").append("svg")
.attr("width", width + margin.right + margin.left)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
root = treeData[k]; //treeData为上边定义的节点属性
root.x0 = height / 2;
root.y0 = 0;
update(root);
function update(source) {
// Compute the new tree layout.计算新树图的布局
var nodes = tree.nodes(root).reverse(),
links = tree.links(nodes);
// Normalize for fixed-depth.设置y坐标点,每层占180px
nodes.forEach(function(d) {
d.y = d.depth * 180;
});
// Update the nodes…每个node对应一个group
var node = svg.selectAll("g.node")
.data(nodes, function(d) {
return d.id || (d.id = ++i);
}); //data():绑定一个数组到选择集上,数组的各项值分别与选择集的各元素绑定
// Enter any new nodes at the parent's previous position.新增节点数据集,设置位置
var nodeEnter = node.enter().append("g") //在 svg 中添加一个g,g是 svg 中的一个属性,是 group 的意思,它表示一组什么东西,如一组 lines , rects ,circles 其实坐标轴就是由这些东西构成的。
.attr("class", "node") //attr设置html属性,style设置css属性
.attr("transform", function(d) {
return "translate(" + source.y0 + "," + source.x0 + ")";
})
.on("click", click);
//添加连接点---此处设置的是圆圈过渡时候的效果(颜色)
// nodeEnter.append("circle")
// .attr("r", 1e-6)
// .style("fill", function(d) { return d._children ? "lightsteelblue" : "#357CAE"; });//d 代表数据,也就是与某元素绑定的数据。
nodeEnter.append("rect")
.attr("x", -23)
.attr("y", -10)
.attr("width", 70)
.attr("height", 20)
.attr("rx", 10)
.style("fill", "#800000"); //d 代表数据,也就是与某元素绑定的数据。
nodeEnter.append("text")
.attr("x", function(d) {
return d.children || d._children ? 13 : 13;
})
.attr("dy", "10")
.attr("text-anchor", "middle")
.text(function(d) {
return d.name;
})
.style("fill", "white")
.style("fill-opacity", 1);
// Transition nodes to their new position.将节点过渡到一个新的位置-----主要是针对节点过渡过程中的过渡效果
//node就是保留的数据集,为原来数据的图形添加过渡动画。首先是整个组的位置
var nodeUpdate = node.transition() //开始一个动画过渡
.duration(duration) //过渡延迟时间,此处主要设置的是圆圈节点随斜线的过渡延迟
.attr("transform", function(d) {
return "translate(" + d.y + "," + d.x + ")";
});
nodeUpdate.select("rect")
.attr("x", -23)
.attr("y", -10)
.attr("width", 70)
.attr("height", 20)
.attr("rx", 10)
.style("fill", "#800000");
nodeUpdate.select("text")
.attr("text-anchor", "middle")
.style("fill-opacity", 1);
// Transition exiting nodes to the parent's new position.过渡现有的节点到父母的新位置。
//最后处理消失的数据,添加消失动画
var nodeExit = node.exit().transition()
.duration(duration)
.attr("transform", function(d) {
return "translate(" + source.y + "," + source.x + ")";
})
.remove();
nodeExit.select("circle")
.attr("r", 1e-6);
nodeExit.select("text")
.attr("text-anchor", "middle")
.style("fill-opacity", 1e-6);
// Update the links…线操作相关
//再处理连线集合
var link = svg.selectAll("path.link")
.data(links, function(d) {
return d.target.id;
});
// Enter any new links at the parent's previous position.
//添加新的连线
link.enter().insert("path", "g")
.attr("class", "link")
.attr("d", function(d) {
var o = {
x: source.x0,
y: source.y0
};
return diagonal({
source: o,
target: o
}); //diagonal - 生成一个二维贝塞尔连接器, 用于节点连接图.
})
.attr('marker-end', 'url(#arrow)');
// Transition links to their new position.将斜线过渡到新的位置
//保留的连线添加过渡动画
link.transition()
.duration(duration)
.attr("d", diagonal);
// Transition exiting nodes to the parent's new position.过渡现有的斜线到父母的新位置。
//消失的连线添加过渡动画
link.exit().transition()
.duration(duration)
.attr("d", function(d) {
var o = {
x: source.x,
y: source.y
};
return diagonal({
source: o,
target: o
});
})
.remove();
// Stash the old positions for transition.将旧的斜线过渡效果隐藏
nodes.forEach(function(d) {
d.x0 = d.x;
d.y0 = d.y;
});
}
//定义一个将某节点折叠的函数
// Toggle children on click.切换子节点事件
function click(d) {
if (d.children) {
d._children = d.children;
d.children = null;
} else {
d.children = d._children;
d._children = null;
}
update(d);
}
}
//d3.select(self.frameElement).style("height", "500px");
// 定义菜单选项
var userMenuData = [
[{
text: "添加",
func: function() {
// id为节点id
var id = $(this).children("text").html();
id = id.substring(id.indexOf("(") + 1, id.indexOf(")"));
showDialog(id);
}
}, {
text: "修改",
func: function() {
var id = $(this).children("text").html();
id = id.substring(id.indexOf("(") + 1, id.indexOf(")"));
showEditDialog(id);
}
}, {
text: "禁用",
func: function() {
var id = $(this).children("text").html();
id = id.substring(id.indexOf("(") + 1, id.indexOf(")"));
}
}, {
text: "删除",
func: function() {
var id = $(this).children("text").html();
id = id.substring(id.indexOf("(") + 1, id.indexOf(")"));
deleteAppModule(id);
}
}]
];
// 事件监听方式添加事件绑定
$("g").smartMenu(userMenuData, {
name: "chatRightControl",
container: "g.node"
});
</script>
</body>
</html>