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