1+ {
2+ "$schema" : " https://vega.github.io/schema/vega/v5.json" ,
3+ "description" : " A node-link diagram with force-directed layout, depicting character co-occurrence in the novel Les Misérables." ,
4+ "width" : 700 ,
5+ "height" : 500 ,
6+ "padding" : 0 ,
7+ "autosize" : " none" ,
8+
9+ "signals" : [
10+ { "name" : " cx" , "update" : " width / 2" },
11+ { "name" : " cy" , "update" : " height / 2" },
12+ { "name" : " nodeRadius" , "value" : 8 ,
13+ "bind" : {"input" : " range" , "min" : 1 , "max" : 50 , "step" : 1 } },
14+ { "name" : " nodeCharge" , "value" : -30 ,
15+ "bind" : {"input" : " range" , "min" :-100 , "max" : 10 , "step" : 1 } },
16+ { "name" : " linkDistance" , "value" : 30 ,
17+ "bind" : {"input" : " range" , "min" : 5 , "max" : 100 , "step" : 1 } },
18+ { "name" : " static" , "value" : true ,
19+ "bind" : {"input" : " checkbox" } },
20+ {
21+ "description" : " State variable for active node fix status." ,
22+ "name" : " fix" , "value" : false ,
23+ "on" : [
24+ {
25+ "events" : " symbol:pointerout[!event.buttons], window:pointerup" ,
26+ "update" : " false"
27+ },
28+ {
29+ "events" : " symbol:pointerover" ,
30+ "update" : " fix || true"
31+ },
32+ {
33+ "events" : " [symbol:pointerdown, window:pointerup] > window:pointermove!" ,
34+ "update" : " xy()" ,
35+ "force" : true
36+ }
37+ ]
38+ },
39+ {
40+ "description" : " Graph node most recently interacted with." ,
41+ "name" : " node" , "value" : null ,
42+ "on" : [
43+ {
44+ "events" : " symbol:pointerover" ,
45+ "update" : " fix === true ? item() : node"
46+ }
47+ ]
48+ },
49+ {
50+ "description" : " Flag to restart Force simulation upon data changes." ,
51+ "name" : " restart" , "value" : false ,
52+ "on" : [
53+ {"events" : {"signal" : " fix" }, "update" : " fix && fix.length" }
54+ ]
55+ }
56+ ],
57+
58+ "data" : [
59+ {
60+ "name" : " node-data" ,
61+ "values" : [],
62+ "format" : {"type" : " json" , "property" : " nodes" }
63+ },
64+ {
65+ "name" : " link-data" ,
66+ "url" : " data/miserables.json" ,
67+ "format" : {"type" : " json" , "property" : " links" }
68+ }
69+ ],
70+
71+ "scales" : [
72+ {
73+ "name" : " color" ,
74+ "type" : " ordinal" ,
75+ "domain" : {"data" : " node-data" , "field" : " group" },
76+ "range" : {"scheme" : " category20c" }
77+ }
78+ ],
79+
80+ "marks" : [
81+ {
82+ "name" : " nodes" ,
83+ "type" : " symbol" ,
84+ "zindex" : 1 ,
85+
86+ "from" : {"data" : " node-data" },
87+ "on" : [
88+ {
89+ "trigger" : " fix" ,
90+ "modify" : " node" ,
91+ "values" : " fix === true ? {fx: node.x, fy: node.y} : {fx: fix[0], fy: fix[1]}"
92+ },
93+ {
94+ "trigger" : " !fix" ,
95+ "modify" : " node" , "values" : " {fx: null, fy: null}"
96+ }
97+ ],
98+
99+ "encode" : {
100+ "enter" : {
101+ "fill" : {"scale" : " color" , "field" : " group" },
102+ "stroke" : {"value" : " white" }
103+ },
104+ "update" : {
105+ "size" : {"signal" : " 2 * nodeRadius * nodeRadius" },
106+ "cursor" : {"value" : " pointer" }
107+ }
108+ },
109+
110+ "transform" : [
111+ {
112+ "type" : " force" ,
113+ "iterations" : 300 ,
114+ "restart" : {"signal" : " restart" },
115+ "static" : {"signal" : " static" },
116+ "signal" : " force" ,
117+ "forces" : [
118+ {"force" : " center" , "x" : {"signal" : " cx" }, "y" : {"signal" : " cy" }},
119+ {"force" : " collide" , "radius" : {"signal" : " nodeRadius" }},
120+ {"force" : " nbody" , "strength" : {"signal" : " nodeCharge" }},
121+ {"force" : " link" , "links" : " link-data" , "distance" : {"signal" : " linkDistance" }}
122+ ]
123+ }
124+ ]
125+ },
126+ {
127+ "type" : " path" ,
128+ "from" : {"data" : " link-data" },
129+ "interactive" : false ,
130+ "encode" : {
131+ "update" : {
132+ "stroke" : {"value" : " #ccc" },
133+ "strokeWidth" : {"value" : 0.5 }
134+ }
135+ },
136+ "transform" : [
137+ {
138+ "type" : " linkpath" ,
139+ "require" : {"signal" : " force" },
140+ "shape" : " line" ,
141+ "sourceX" : " datum.source.x" , "sourceY" : " datum.source.y" ,
142+ "targetX" : " datum.target.x" , "targetY" : " datum.target.y"
143+ }
144+ ]
145+ }
146+ ]
147+ }
0 commit comments