1
+ <!DOCTYPE html>
2
+ < html lang ="en ">
3
+ < head >
4
+ < meta charset ="utf-8 ">
5
+ < title > Tree Example</ title >
6
+ < style >
7
+ .node {
8
+ cursor : pointer;
9
+ }
10
+
11
+ .node circle {
12
+ fill : # fff ;
13
+ stroke : steelblue;
14
+ stroke-width : 3px ;
15
+ }
16
+
17
+ .node text {
18
+ font : 12px sans-serif;
19
+ }
20
+
21
+ .link {
22
+ fill : none;
23
+ stroke : # ccc ;
24
+ stroke-width : 2px ;
25
+ }
26
+ </ style >
27
+ </ head >
28
+ < body >
29
+ < script src ="https://polyfill.io/v3/polyfill.min.js "> </ script >
30
+ < script src ="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js "> </ script >
31
+ < script >
32
+ // Adapted from https://bl.ocks.org/d3noob/8375092
33
+ var margin = { top : 20 , right : 120 , bottom : 20 , left : 120 } ,
34
+ width = 960 - margin . right - margin . left ,
35
+ height = 500 - margin . top - margin . bottom ;
36
+
37
+ var i = 0 ,
38
+ duration = 750 ,
39
+ root ,
40
+ tree ,
41
+ svg ,
42
+ diagonal ,
43
+ treeData ;
44
+
45
+ fetch ( window . location . protocol + '/data.json' )
46
+ . then ( response => response . json ( ) )
47
+ . then ( json => draw ( json ) ) ;
48
+
49
+ function draw ( json ) {
50
+ treeData = [ json ] ; // Needs to be in an array
51
+
52
+ tree = d3 . layout . tree ( ) . size ( [ height , width ] ) ;
53
+
54
+ diagonal = d3 . svg . diagonal ( ) . projection ( function ( d ) { return [ d . y , d . x ] ; } ) ;
55
+
56
+ svg = d3 . select ( "body" ) . append ( "svg" )
57
+ . attr ( "width" , width + margin . right + margin . left )
58
+ . attr ( "height" , height + margin . top + margin . bottom )
59
+ . append ( "g" )
60
+ . attr ( "transform" , "translate(" + margin . left + "," + margin . top + ")" ) ;
61
+
62
+ root = treeData [ 0 ] ;
63
+ root . x0 = height / 2 ;
64
+ root . y0 = 0 ;
65
+
66
+ update ( root ) ;
67
+
68
+ d3 . select ( self . frameElement ) . style ( "height" , "500px" ) ;
69
+ }
70
+
71
+ function update ( source ) {
72
+
73
+ // Compute the new tree layout.
74
+ var nodes = tree . nodes ( root ) . reverse ( ) ,
75
+ links = tree . links ( nodes ) ;
76
+
77
+ // Normalize for fixed-depth.
78
+ nodes . forEach ( function ( d ) { d . y = d . depth * 180 ; } ) ;
79
+
80
+ // Update the nodes…
81
+ var node = svg . selectAll ( "g.node" )
82
+ . data ( nodes , function ( d ) { return d . id || ( d . id = ++ i ) ; } ) ;
83
+
84
+ // Enter any new nodes at the parent's previous position.
85
+ var nodeEnter = node . enter ( ) . append ( "g" )
86
+ . attr ( "class" , "node" )
87
+ . attr ( "transform" , function ( d ) { return "translate(" + source . y0 + "," + source . x0 + ")" ; } )
88
+ . on ( "click" , click ) ;
89
+
90
+ nodeEnter . append ( "circle" )
91
+ . attr ( "r" , 1e-6 )
92
+ . style ( "fill" , function ( d ) { return d . _children ? "lightsteelblue" : "#fff" ; } ) ;
93
+
94
+ nodeEnter . append ( "text" )
95
+ . attr ( "x" , function ( d ) { return d . children || d . _children ? - 13 : 13 ; } )
96
+ . attr ( "dy" , ".35em" )
97
+ . attr ( "text-anchor" , function ( d ) { return d . children || d . _children ? "end" : "start" ; } )
98
+ . text ( function ( d ) { return d . name ; } )
99
+ . style ( "fill-opacity" , 1e-6 ) ;
100
+
101
+ // Transition nodes to their new position.
102
+ var nodeUpdate = node . transition ( )
103
+ . duration ( duration )
104
+ . attr ( "transform" , function ( d ) { return "translate(" + d . y + "," + d . x + ")" ; } ) ;
105
+
106
+ nodeUpdate . select ( "circle" )
107
+ . attr ( "r" , 10 )
108
+ . style ( "fill" , function ( d ) { return d . _children ? "lightsteelblue" : "#fff" ; } ) ;
109
+
110
+ nodeUpdate . select ( "text" )
111
+ . style ( "fill-opacity" , 1 ) ;
112
+
113
+ // Transition exiting nodes to the parent's new position.
114
+ var nodeExit = node . exit ( ) . transition ( )
115
+ . duration ( duration )
116
+ . attr ( "transform" , function ( d ) { return "translate(" + source . y + "," + source . x + ")" ; } )
117
+ . remove ( ) ;
118
+
119
+ nodeExit . select ( "circle" )
120
+ . attr ( "r" , 1e-6 ) ;
121
+
122
+ nodeExit . select ( "text" )
123
+ . style ( "fill-opacity" , 1e-6 ) ;
124
+
125
+ // Update the links…
126
+ var link = svg . selectAll ( "path.link" )
127
+ . data ( links , function ( d ) { return d . target . id ; } ) ;
128
+
129
+ // Enter any new links at the parent's previous position.
130
+ link . enter ( ) . insert ( "path" , "g" )
131
+ . attr ( "class" , "link" )
132
+ . attr ( "d" , function ( d ) {
133
+ var o = { x : source . x0 , y : source . y0 } ;
134
+ return diagonal ( { source : o , target : o } ) ;
135
+ } ) ;
136
+
137
+ // Transition links to their new position.
138
+ link . transition ( )
139
+ . duration ( duration )
140
+ . attr ( "d" , diagonal ) ;
141
+
142
+ // Transition exiting nodes to the parent's new position.
143
+ link . exit ( ) . transition ( )
144
+ . duration ( duration )
145
+ . attr ( "d" , function ( d ) {
146
+ var o = { x : source . x , y : source . y } ;
147
+ return diagonal ( { source : o , target : o } ) ;
148
+ } )
149
+ . remove ( ) ;
150
+
151
+ // Stash the old positions for transition.
152
+ nodes . forEach ( function ( d ) {
153
+ d . x0 = d . x ;
154
+ d . y0 = d . y ;
155
+ } ) ;
156
+ }
157
+
158
+ // Toggle children on click.
159
+ function click ( d ) {
160
+ if ( d . children ) {
161
+ d . _children = d . children ;
162
+ d . children = null ;
163
+ } else {
164
+ d . children = d . _children ;
165
+ d . _children = null ;
166
+ }
167
+ update ( d ) ;
168
+ }
169
+ </ script >
170
+ </ body >
171
+ </ html >
0 commit comments