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