@@ -2,43 +2,27 @@ import { updateSelectedNodes } from "../tabular";
2
2
import { getGraphData } from "../model" ;
3
3
import { updateSelection , setLastSelectedNode } from "../selection" ;
4
4
5
- export function update ( ) {
6
-
7
- var graph = getGraphData ( ) ;
8
-
9
- var shiftKey , ctrlKey ,
10
- width = window . innerWidth ,
11
- height = window . innerHeight ;
12
-
13
- var zoomer = d3 . zoom ( )
14
- . scaleExtent ( [ 1 / 4 , 40 ] )
5
+ let shiftKey , ctrlKey ,
6
+ width = window . innerWidth ,
7
+ height = window . innerHeight ,
8
+ foreverUniq = 0 ;
9
+
10
+ let svg = null ,
11
+ brush = null ,
12
+ node ,
13
+ link ,
14
+ links ,
15
+ nodes ,
16
+ zoomer = d3 . zoom ( )
17
+ . scaleExtent ( [ 1 / 4 , 100 ] )
15
18
. on ( "zoom" , ( ) => {
16
19
view . attr ( "transform" , d3 . event . transform ) ;
17
- } ) ;
18
-
19
- var dragger = d3 . drag ( )
20
+ } ) ,
21
+ dragger = d3 . drag ( )
20
22
. on ( "start" , dragstarted )
21
23
. on ( "drag" , dragged )
22
- . on ( "end" , dragended ) ;
23
-
24
- d3 . select ( window )
25
- . on ( "keydown" , keyDown )
26
- . on ( "keyup" , keyUp ) ;
27
-
28
- var svg = d3 . select ( "#graph" )
29
- . call ( zoomer ) ;
30
-
31
- var view = svg
32
- . append ( "g" )
33
- . attr ( "class" , "view" ) ;
34
-
35
- var brush = view . append ( "g" )
36
- . datum ( ( ) => { return { selected : false , previouslySelected : false } ; } )
37
- . attr ( "class" , "brush" ) ;
38
-
39
- // var color = d3.scaleOrdinal(d3.schemeCategory20);
40
-
41
- var simulation = d3 . forceSimulation ( )
24
+ . on ( "end" , dragended ) ,
25
+ simulation = d3 . forceSimulation ( )
42
26
. force ( "link" ,
43
27
d3 . forceLink ( )
44
28
. distance ( d => 50 + ( d . source . radius + d . target . radius ) * 2 )
@@ -48,25 +32,125 @@ export function update () {
48
32
d3 . forceManyBody ( )
49
33
. strength ( d => { return - 10 * d . radius ; } )
50
34
)
51
- . force ( "center" , d3 . forceCenter ( width / 2 , height / 2 ) ) ;
35
+ . force ( "center" , d3 . forceCenter ( width / 2 , height / 2 ) ) ,
36
+ brusher = d3 . brush ( )
37
+ . extent ( [ [ - 9999999 , - 9999999 ] , [ 9999999 , 9999999 ] ] )
38
+ . on ( "start.brush" , ( ) => {
39
+ if ( ! d3 . event . sourceEvent ) return ;
40
+ node . each ( ( d ) => {
41
+ d . previouslySelected = ctrlKey && d . selected ;
42
+ } ) ;
43
+ } )
44
+ . on ( "brush.brush" , ( ) => {
45
+ if ( ! d3 . event . sourceEvent ) return ;
46
+ let extent = d3 . event . selection ;
47
+ if ( ! extent )
48
+ return ;
49
+ node . classed ( "selected" , ( d ) => {
50
+ let selected = ( extent [ 0 ] [ 0 ] <= d . x && d . x < extent [ 1 ] [ 0 ]
51
+ && extent [ 0 ] [ 1 ] <= d . y && d . y < extent [ 1 ] [ 1 ] ) ;
52
+ if ( selected ) setLastSelectedNode ( d ) ;
53
+ return d . selected = d . previouslySelected ^ selected ;
54
+ } ) ;
55
+ } )
56
+ . on ( "end.brush" , ( ) => {
57
+ if ( ! d3 . event . sourceEvent ) return ;
58
+ setTimeout ( ( ) => {
59
+ brush . call ( brusher . move , null ) ;
60
+ updateSelection ( ) ;
61
+ } , 25 ) ;
62
+ } ) ,
63
+ view = null ;
64
+
65
+ function ticked ( ) {
66
+ link
67
+ . attr ( "x1" , d => d . source . x )
68
+ . attr ( "y1" , d => d . source . y )
69
+ . attr ( "x2" , d => d . target . x )
70
+ . attr ( "y2" , d => d . target . y ) ;
71
+ node
72
+ . attr ( "transform" , ( d ) => `translate(${ d . x } ,${ d . y } )` )
73
+ }
74
+
75
+ function dragstarted ( d ) {
76
+ if ( ! d3 . event . active ) simulation . alphaTarget ( 0.3 ) . restart ( ) ;
77
+ d . fx = d . x ;
78
+ d . fy = d . y ;
79
+ }
80
+
81
+ function dragged ( d ) {
82
+ d . fx = d3 . event . x ;
83
+ d . fy = d3 . event . y ;
84
+ }
85
+
86
+ function dragended ( d ) {
87
+ if ( ! d3 . event . active ) simulation . alphaTarget ( 0 ) ;
88
+ d . fx = null ;
89
+ d . fy = null ;
90
+ }
91
+
92
+ function keyDown ( ) {
93
+ shiftKey = d3 . event . shiftKey || d3 . event . metaKey ;
94
+ ctrlKey = d3 . event . ctrlKey ;
95
+
96
+ if ( d3 . event . keyCode == 67 ) { // the 'c' key
97
+ // do stuff
98
+ }
99
+
100
+ if ( ctrlKey ) {
101
+ brush . select ( '.overlay' ) . style ( 'cursor' , 'crosshair' ) ;
102
+ brush . call ( brusher ) ;
103
+ d3 . event . preventDefault ( ) ;
104
+ }
105
+ }
106
+
107
+ function keyUp ( ) {
108
+ shiftKey = d3 . event . shiftKey || d3 . event . metaKey ;
109
+ ctrlKey = d3 . event . ctrlKey ;
52
110
53
- var link = view . append ( "g" )
54
- . attr ( "class" , "links" )
55
- . selectAll ( "line" )
56
- . data ( graph . edges )
57
- . enter ( ) . append ( "line" )
111
+ brush . call ( brusher )
112
+ . on ( ".brush" , null ) ;
113
+
114
+ brush . select ( '.overlay' ) . style ( 'cursor' , 'auto' ) ;
115
+ }
116
+
117
+ export function init ( ) {
118
+ svg = d3 . select ( "#graph" )
119
+ . call ( zoomer ) ;
120
+ view = svg
121
+ . append ( "g" )
122
+ . attr ( "class" , "view" ) ;
123
+ brush = view . append ( "g" )
124
+ . datum ( ( ) => { return { selected : false , previouslySelected : false } ; } )
125
+ . attr ( "class" , "brush" ) ;
126
+ links = view . append ( "g" ) . attr ( "class" , "links" ) ;
127
+ nodes = view . append ( "g" ) . attr ( "class" , "nodes" ) ;
128
+ link = links . selectAll ( "line" ) ;
129
+ node = nodes . selectAll ( ".node" ) ;
130
+ d3 . select ( window )
131
+ . on ( "keydown" , keyDown )
132
+ . on ( "keyup" , keyUp ) ;
133
+ }
134
+
135
+ export function update ( ) {
136
+
137
+ let graph = getGraphData ( ) ;
138
+
139
+ link = link
140
+ . data ( graph . edges , ( d ) => foreverUniq ++ ) ;
141
+ link . exit ( ) . remove ( ) ;
142
+ link = link . enter ( ) . append ( "line" )
58
143
. attr ( "class" , d => d . type === "similar"
59
144
? "similar"
60
145
: d . type === "related"
61
146
? "related"
62
147
: "other"
63
148
) ;
64
149
65
- var node = view . append ( "g" )
66
- . attr ( "class" , "nodes" )
67
- . selectAll ( ".node" )
68
- . data ( graph . nodes )
69
- . enter ( ) . append ( "g" )
150
+ node = node
151
+ . data ( graph . nodes , ( d ) => foreverUniq ++ ) ;
152
+ node . exit ( ) . remove ( ) ;
153
+ node = node . enter ( ) . append ( "g" )
70
154
. attr ( "class" , "node" )
71
155
. call ( dragger )
72
156
. on ( "dblclick" , ( ) => d3 . event . stopPropagation ( ) )
@@ -80,106 +164,31 @@ export function update () {
80
164
updateSelection ( ) ;
81
165
} ) ;
82
166
83
- var circle = node . append ( "circle" )
167
+ node . append ( "circle" )
84
168
. attr ( "r" , d => d . radius ) ;
85
169
86
170
node . append ( "text" )
87
171
. attr ( "dy" , ".3em" )
88
172
. attr ( "style" , d => `font-size:${ Math . round ( d . radius / 2 ) } px` )
89
173
. text ( d => d . label ) ;
90
174
175
+ node . exit ( ) . remove ( ) ;
176
+ link . exit ( ) . remove ( ) ;
177
+
91
178
simulation
92
179
. nodes ( graph . nodes )
93
180
. on ( "tick" , ticked ) ;
94
181
95
182
simulation . force ( "link" )
96
183
. links ( graph . edges ) ;
97
184
98
- var brusher = d3 . brush ( )
99
- . extent ( [ [ - 9999999 , - 9999999 ] , [ 9999999 , 9999999 ] ] )
100
- . on ( "start.brush" , ( ) => {
101
- if ( ! d3 . event . sourceEvent ) return ;
102
- node . each ( ( d ) => {
103
- d . previouslySelected = ctrlKey && d . selected ;
104
- } ) ;
105
- } )
106
- . on ( "brush.brush" , ( ) => {
107
- if ( ! d3 . event . sourceEvent ) return ;
108
- var extent = d3 . event . selection ;
109
- if ( ! extent )
110
- return ;
111
- node . classed ( "selected" , ( d ) => {
112
- let selected = ( extent [ 0 ] [ 0 ] <= d . x && d . x < extent [ 1 ] [ 0 ]
113
- && extent [ 0 ] [ 1 ] <= d . y && d . y < extent [ 1 ] [ 1 ] ) ;
114
- if ( selected ) setLastSelectedNode ( d ) ;
115
- return d . selected = d . previouslySelected ^ selected ;
116
- } ) ;
117
- } )
118
- . on ( "end.brush" , ( ) => {
119
- if ( ! d3 . event . sourceEvent ) return ;
120
- setTimeout ( ( ) => {
121
- brush . call ( brusher . move , null ) ;
122
- updateSelection ( ) ;
123
- } , 25 ) ;
124
- } ) ;
185
+ simulation . restart ( ) ;
125
186
126
187
brush . call ( brusher )
127
188
. on ( ".brush" , null ) ;
128
189
129
190
brush . select ( '.overlay' ) . style ( 'cursor' , 'auto' ) ;
130
191
131
- for ( var i = 100 ; i > 0 ; -- i ) simulation . tick ( ) ;
132
-
133
- function ticked ( ) {
134
- link
135
- . attr ( "x1" , d => d . source . x )
136
- . attr ( "y1" , d => d . source . y )
137
- . attr ( "x2" , d => d . target . x )
138
- . attr ( "y2" , d => d . target . y ) ;
139
- node
140
- . attr ( "transform" , ( d ) => `translate(${ d . x } ,${ d . y } )` )
141
- }
142
-
143
- function dragstarted ( d ) {
144
- if ( ! d3 . event . active ) simulation . alphaTarget ( 0.3 ) . restart ( ) ;
145
- d . fx = d . x ;
146
- d . fy = d . y ;
147
- }
148
-
149
- function dragged ( d ) {
150
- d . fx = d3 . event . x ;
151
- d . fy = d3 . event . y ;
152
- }
153
-
154
- function dragended ( d ) {
155
- if ( ! d3 . event . active ) simulation . alphaTarget ( 0 ) ;
156
- d . fx = null ;
157
- d . fy = null ;
158
- }
159
-
160
- function keyDown ( ) {
161
- shiftKey = d3 . event . shiftKey || d3 . event . metaKey ;
162
- ctrlKey = d3 . event . ctrlKey ;
163
-
164
- if ( d3 . event . keyCode == 67 ) { // the 'c' key
165
- // do stuff
166
- }
167
-
168
- if ( ctrlKey ) {
169
- brush . select ( '.overlay' ) . style ( 'cursor' , 'crosshair' ) ;
170
- brush . call ( brusher ) ;
171
- d3 . event . preventDefault ( ) ;
172
- }
173
- }
174
-
175
- function keyUp ( ) {
176
- shiftKey = d3 . event . shiftKey || d3 . event . metaKey ;
177
- ctrlKey = d3 . event . ctrlKey ;
178
-
179
- brush . call ( brusher )
180
- . on ( ".brush" , null ) ;
181
-
182
- brush . select ( '.overlay' ) . style ( 'cursor' , 'auto' ) ;
183
- }
192
+ for ( let i = 100 ; i > 0 ; -- i ) simulation . tick ( ) ;
184
193
185
194
}
0 commit comments