@@ -2,7 +2,9 @@ import React, { Component } from 'react';
2
2
import '../styles/components/_d3Tree.scss' ;
3
3
import * as d3 from 'd3' ;
4
4
5
- let root ;
5
+ var root = { } ;
6
+ let duration = 750 ;
7
+
6
8
7
9
class Chart extends Component {
8
10
constructor ( props ) {
@@ -14,189 +16,203 @@ class Chart extends Component {
14
16
this . maked3Tree ( ) ;
15
17
}
16
18
17
- componentWillUpdate ( prevProps ) {
18
- if ( this . props . snapshot !== prevProps . snapshot ) {
19
- root = JSON . parse ( JSON . stringify ( prevProps . snapshot ) ) ;
20
- this . maked3Tree ( ) ;
21
- }
19
+ componentWillUpdate ( newProps ) {
20
+ if ( this . props . snapshot !== newProps . snapshot ) {
21
+ root = JSON . parse ( JSON . stringify ( newProps . snapshot ) ) ;
22
+ this . maked3Tree ( ) ;
23
+ }
22
24
}
23
-
25
+
24
26
removed3Tree ( ) {
25
27
const { anchor } = this . refs ;
26
28
while ( anchor . hasChildNodes ( ) ) {
27
29
anchor . removeChild ( anchor . lastChild ) ;
28
30
}
29
31
}
30
-
31
- maked3Tree ( ) {
32
+
33
+ maked3Tree ( ) {
32
34
this . removed3Tree ( ) ;
35
+ duration = 0 ;
36
+
37
+ var margin = { top : 20 , right : 120 , bottom : 20 , left : 120 } ,
38
+ width = 960 - margin . right - margin . left ,
39
+ height = 800 - margin . top - margin . bottom ;
33
40
34
- const margin = {
35
- top : 20 ,
36
- right : 120 ,
37
- bottom : 20 ,
38
- left : 120 ,
39
- } ;
40
- const width = 960 - margin . right - margin . left ;
41
- const height = 800 - margin . top - margin . bottom ;
41
+ var i = 0 ;
42
42
43
- let i = 0 ;
44
- const duration = 750 ;
43
+ var tree = d3 . layout . tree ( )
44
+ . size ( [ 400 , 400 ] ) ;
45
45
46
- const tree = d3 . layout . tree ( ) . size ( [ height , width ] ) ;
46
+ var diagonal = d3 . svg . diagonal ( )
47
+ . projection ( function ( d ) { return [ d . y , d . x ] ; } ) ;
47
48
48
- const diagonal = d3 . svg . diagonal ( ) . projection ( d => [ d . y , d . x ] ) ;
49
+ var svg = d3 . select ( this . refs . anchor ) . append ( "svg" )
50
+ . attr ( "width" , width + margin . right + margin . left )
51
+ . attr ( "height" , height + margin . top + margin . bottom )
52
+ . append ( "g" )
53
+ . attr ( "transform" , "translate(" + margin . left + "," + margin . top + ")" ) ;
49
54
50
- const svg = d3
51
- . select ( this . refs . anchor )
52
- . append ( 'svg' )
53
- . attr ( 'width' , width + margin . right + margin . left )
54
- . attr ( 'height' , height + margin . top + margin . bottom )
55
- . append ( 'g' )
56
- . attr ( 'transform' , `translate(${ margin . left } ,${ margin . top } )` ) ;
55
+ // Add tooltip div
56
+ var div = d3 . select ( "body" ) . append ( "div" )
57
+ . attr ( "class" , "tooltip" )
58
+ . style ( "opacity" , 1e-6 )
59
+ . on ( "mouseover" , tipMouseover )
60
+ . on ( "mouseout" , tipMouseout )
57
61
58
62
root . x0 = height / 2 ;
59
63
root . y0 = 0 ;
60
-
64
+
61
65
function update ( source ) {
62
- // Compute the new tree layout.
63
- const nodes = tree . nodes ( root ) . reverse ( ) ;
64
- const links = tree . links ( nodes ) ;
65
-
66
- // Normalize for fixed-depth.
67
- nodes . forEach ( ( d ) => {
68
- d . y = d . depth * 180 ;
69
- } ) ;
70
-
71
- // Update the nodes…
72
- const node = svg . selectAll ( 'g.node' ) . data ( nodes , d => d . id || ( d . id = ++ i ) ) ;
73
-
74
- // Enter any new nodes at the parent's previous position.
75
- const nodeEnter = node
76
- . enter ( )
77
- . append ( 'g' )
78
- . attr ( 'class' , 'node' )
79
- . attr ( 'transform' , d => `translate(${ source . y0 } ,${ source . x0 } )` )
80
- . on ( 'click' , click )
81
- . on ( 'mouseover' , mouseover )
82
- . on ( 'mouseout' , mouseout ) ;
83
-
84
- nodeEnter
85
- . append ( 'circle' )
86
- . attr ( 'r' , 1e-6 )
87
- . style ( 'fill' , d => ( d . _children ? 'lightsteelblue' : '#fff' ) ) ;
88
-
89
- nodeEnter
90
- . append ( 'text' )
91
- . attr ( 'x' , d => ( d . children || d . _children ? - 10 : 10 ) )
92
- . attr ( 'dy' , '.35em' )
93
- . attr ( 'text-anchor' , d => ( d . children || d . _children ? 'end' : 'start' ) )
94
- . text ( d => d . name )
95
- . style ( 'fill-opacity' , 1e-6 ) ;
96
-
97
- // Transition nodes to their new position.
98
- const nodeUpdate = node
99
- . transition ( )
100
- . duration ( duration )
101
- . attr ( 'transform' , d => `translate(${ d . y } ,${ d . x } )` ) ;
102
-
103
- nodeUpdate
104
- . select ( 'circle' )
105
- . attr ( 'r' , 4.5 )
106
- . style ( 'fill' , d => ( d . _children ? 'lightsteelblue' : '#fff' ) ) ;
107
-
108
- nodeUpdate . select ( 'text' ) . style ( 'fill-opacity' , 1 ) ;
109
-
110
- // Transition exiting nodes to the parent's new position.
111
- const nodeExit = node
112
- . exit ( )
113
- . transition ( )
114
- . duration ( duration )
115
- . attr ( 'transform' , d => `translate(${ source . y } ,${ source . x } )` )
116
- . remove ( ) ;
117
-
118
- nodeExit . select ( 'circle' ) . attr ( 'r' , 1e-6 ) ;
119
-
120
- nodeExit . select ( 'text' ) . style ( 'fill-opacity' , 1e-6 ) ;
121
-
122
- // Update the links…
123
- const link = svg . selectAll ( 'path.link' ) . data ( links , d => d . target . id ) ;
124
-
125
- // Enter any new links at the parent's previous position.
126
- link
127
- . enter ( )
128
- . insert ( 'path' , 'g' )
129
- . attr ( 'class' , 'link' )
130
- . attr ( 'd' , ( d ) => {
131
- const o = { x : source . x0 , y : source . y0 } ;
132
- return diagonal ( { source : o , target : o } ) ;
133
- } ) ;
134
-
135
- // Transition links to their new position.
136
- link
137
- . transition ( )
138
- . duration ( duration )
139
- . attr ( 'd' , diagonal ) ;
140
-
141
- // Transition exiting nodes to the parent's new position.
142
- link
143
- . exit ( )
144
- . transition ( )
145
- . duration ( duration )
146
- . attr ( 'd' , ( d ) => {
147
- const o = { x : source . x , y : source . y } ;
148
- return diagonal ( { source : o , target : o } ) ;
149
- } )
150
- . remove ( ) ;
151
-
152
- // Stash the old positions for transition.
153
- nodes . forEach ( ( d ) => {
66
+ // Compute the new tree layout.
67
+ var nodes = tree . nodes ( root ) . reverse ( ) ,
68
+ links = tree . links ( nodes ) ;
69
+
70
+ // Normalize for fixed-depth.
71
+ nodes . forEach ( function ( d ) { d . y = d . depth * 180 ; } ) ;
72
+
73
+ // Update the nodes…
74
+ var node = svg . selectAll ( "g.node" )
75
+ . data ( nodes , function ( d ) { return d . id || ( d . id = ++ i ) ; } ) ;
76
+
77
+ // Enter any new nodes at the parent's previous position.
78
+ var nodeEnter = node . enter ( ) . append ( "g" )
79
+ . attr ( "class" , "node" )
80
+ . attr ( "transform" , function ( d ) { return "translate(" + source . y0 + "," + source . x0 + ")" ; } )
81
+ . on ( "click" , click )
82
+ . on ( "mouseover" , mouseover )
83
+ . on ( "mouseout" , mouseout )
84
+ . on ( "mousemove" , function ( d ) { mousemove ( d ) ; } ) ;
85
+
86
+
87
+ nodeEnter . append ( "circle" )
88
+ . attr ( "r" , 1e-6 )
89
+ . style ( "fill" , function ( d ) { return d . _children ? "lightsteelblue" : "#fff" ; } ) ;
90
+
91
+ nodeEnter . append ( "text" )
92
+ . attr ( "x" , function ( d ) { return d . children || d . _children ? - 10 : 10 ; } )
93
+ . attr ( "dy" , ".35em" )
94
+ . attr ( "text-anchor" , function ( d ) { return d . children || d . _children ? "end" : "start" ; } )
95
+ . text ( function ( d ) { return d . name ; } )
96
+ . style ( 'fill' , '#6FB3D2' )
97
+ . style ( "fill-opacity" , 1e-6 ) ;
98
+
99
+ // Transition nodes to their new position.
100
+ var nodeUpdate = node . transition ( )
101
+ . duration ( duration )
102
+ . attr ( "transform" , function ( d ) { return "translate(" + d . y + "," + d . x + ")" ; } ) ;
103
+
104
+ nodeUpdate . select ( "circle" )
105
+ . attr ( "r" , 7 )
106
+ . style ( "fill" , function ( d ) { return d . _children ? "#A1C658" : "#D381C3" ; } ) ;
107
+
108
+ nodeUpdate . select ( "text" )
109
+ . style ( "fill-opacity" , 1 ) ;
110
+
111
+ // Transition exiting nodes to the parent's new position.
112
+ var nodeExit = node . exit ( ) . transition ( )
113
+ . duration ( duration )
114
+ . attr ( "transform" , function ( d ) { return "translate(" + source . y + "," + source . x + ")" ; } )
115
+ . remove ( ) ;
116
+
117
+ nodeExit . select ( "circle" )
118
+ . attr ( "r" , 1e-6 ) ;
119
+
120
+ nodeExit . select ( "text" )
121
+ . style ( "fill-opacity" , 1e-6 ) ;
122
+
123
+ // Update the links…
124
+ var link = svg . selectAll ( "path.link" )
125
+ . data ( links , function ( d ) { return d . target . id ; } ) ;
126
+
127
+ // Enter any new links at the parent's previous position.
128
+ link . enter ( ) . insert ( "path" , "g" )
129
+ . attr ( "class" , "link" )
130
+ . attr ( "d" , function ( d ) {
131
+ var o = { x : source . x0 , y : source . y0 } ;
132
+ return diagonal ( { source : o , target : o } ) ;
133
+ } ) ;
134
+
135
+ // Transition links to their new position.
136
+ link . transition ( )
137
+ . duration ( duration )
138
+ . attr ( "d" , diagonal ) ;
139
+
140
+ // Transition exiting nodes to the parent's new position.
141
+ link . exit ( ) . transition ( )
142
+ . duration ( duration )
143
+ . attr ( "d" , function ( d ) {
144
+ var o = { x : source . x , y : source . y } ;
145
+ return diagonal ( { source : o , target : o } ) ;
146
+ } )
147
+ . remove ( ) ;
148
+
149
+ // Stash the old positions for transition.
150
+ nodes . forEach ( function ( d ) {
154
151
d . x0 = d . x ;
155
152
d . y0 = d . y ;
156
- } ) ;
153
+ } ) ;
157
154
}
158
-
155
+
159
156
// Toggle children on click.
160
157
function click ( d ) {
161
- if ( d . children ) {
158
+ if ( d . children ) {
162
159
d . _children = d . children ;
163
160
d . children = null ;
164
- } else {
161
+ } else {
165
162
d . children = d . _children ;
166
163
d . _children = null ;
167
- }
168
- update ( d ) ;
164
+ }
165
+ update ( d ) ;
169
166
}
170
167
171
168
// Show state on mouse over
172
- function mouseover ( d ) {
173
- d3 . select ( this )
174
- . append ( 'text' )
175
- . attr ( 'class' , 'hover' )
176
- . attr ( 'transform' , d => 'translate(5, -10)' )
177
- . text ( d . state === undefined ? '' : JSON . stringify ( d . state ) ) ;
169
+ function mouseover ( ) {
170
+ div . transition ( )
171
+ . duration ( 300 )
172
+ . style ( "display" , "block" )
173
+ . style ( "opacity" , 1 )
174
+ }
175
+
176
+ function mouseout ( ) {
177
+ div . transition ( )
178
+ . duration ( 3000 )
179
+ . style ( "opacity" , 1e-6 )
180
+ . style ( "display" , "none" ) ;
178
181
}
179
182
180
- // Toggle children on click.
181
- function mouseout ( d ) {
182
- d3 . select ( this )
183
- . select ( 'text.hover' )
184
- . remove ( ) ;
183
+ function tipMouseover ( ) {
184
+ div . transition ( )
185
+ . duration ( 300 )
186
+ . style ( "opacity" , 1 ) ;
185
187
}
186
188
189
+ function tipMouseout ( ) {
190
+ div . transition ( )
191
+ . duration ( 3000 )
192
+ . style ( "opacity" , 1e-6 )
193
+ . style ( "display" , "none" ) ;
194
+ }
195
+
196
+ function mousemove ( d ) {
197
+ div
198
+ . text ( d . state == undefined ? 'No state found' : JSON . stringify ( d . state , null , 4 ) )
199
+ . style ( "left" , ( d3 . event . pageX ) + "px" )
200
+ . style ( "top" , ( d3 . event . pageY ) + "px" ) ;
201
+ }
202
+
187
203
function collapse ( d ) {
188
- if ( d . children ) {
204
+ if ( d . children ) {
189
205
d . _children = d . children ;
190
206
d . _children . forEach ( collapse ) ;
191
207
d . children = null ;
192
- }
208
+ }
193
209
}
194
-
195
- // root.children.forEach(collapse);
210
+
196
211
update ( root ) ;
197
-
198
- // d3.select(self.frameElement).style("height", "800px");
199
- }
212
+ duration = 750 ;
213
+
214
+ // root.children.forEach(collapse);
215
+ }
200
216
201
217
render ( ) {
202
218
return < div ref = "anchor" className = "d3Container" width = "100%" /> ;
0 commit comments