2
2
@author David Piegza
3
3
4
4
Implements a simple graph drawing with force-directed placement in 2D and 3D.
5
-
5
+
6
6
It uses the force-directed-layout implemented in:
7
7
https://github.com/davidpiegza/Graph-Visualization/blob/master/layouts/force-directed-layout.js
8
-
8
+
9
9
Drawing is done with Three.js: http://github.com/mrdoob/three.js
10
10
11
11
To use this drawing, include the graph-min.js file and create a SimpleGraph object:
12
-
12
+
13
13
<!DOCTYPE html>
14
14
<html>
15
15
<head>
19
19
<body onload="new Drawing.SimpleGraph({layout: '3d', showStats: true, showInfo: true})">
20
20
</bod>
21
21
</html>
22
-
22
+
23
23
Parameters:
24
24
options = {
25
25
layout: "2d" or "3d"
35
35
36
36
37
37
limit: <int>, maximum number of nodes
38
-
38
+
39
39
numNodes: <int> - sets the number of nodes to create.
40
- numEdges: <int> - sets the maximum number of edges for a node. A node will have
40
+ numEdges: <int> - sets the maximum number of edges for a node. A node will have
41
41
1 to numEdges edges, this is set randomly.
42
42
}
43
-
43
+
44
44
45
45
Feel free to contribute a new drawing!
46
46
47
47
*/
48
-
48
+
49
49
var Drawing = Drawing || { } ;
50
50
51
51
Drawing . SimpleGraph = function ( options ) {
52
52
var options = options || { } ;
53
-
53
+
54
54
this . layout = options . layout || "2d" ;
55
55
this . layout_options = options . graphLayout || { } ;
56
56
this . show_stats = options . showStats || false ;
@@ -61,13 +61,13 @@ Drawing.SimpleGraph = function(options) {
61
61
this . nodes_count = options . numNodes || 20 ;
62
62
this . edges_count = options . numEdges || 10 ;
63
63
64
- var camera , scene , renderer , interaction , geometry , object_selection ;
64
+ var camera , controls , scene , renderer , interaction , geometry , object_selection ;
65
65
var stats ;
66
66
var info_text = { } ;
67
67
var graph = new Graph ( { limit : options . limit } ) ;
68
-
68
+
69
69
var geometries = [ ] ;
70
-
70
+
71
71
var that = this ;
72
72
73
73
init ( ) ;
@@ -76,40 +76,37 @@ Drawing.SimpleGraph = function(options) {
76
76
77
77
function init ( ) {
78
78
// Three.js initialization
79
- renderer = new THREE . WebGLRenderer ( { antialias : true } ) ;
79
+ renderer = new THREE . WebGLRenderer ( { alpha : true } ) ;
80
80
renderer . setSize ( window . innerWidth , window . innerHeight ) ;
81
-
82
- camera = new THREE . TrackballCamera ( {
83
- fov : 40 ,
84
- aspect : window . innerWidth / window . innerHeight ,
85
- near : 1 ,
86
- far : 1000000 ,
87
-
88
- rotateSpeed : 0.5 ,
89
- zoomSpeed : 5.2 ,
90
- panSpeed : 1 ,
91
-
92
- noZoom : false ,
93
- noPan : false ,
94
-
95
- staticMoving : false ,
96
- dynamicDampingFactor : 0.3 ,
97
-
98
- domElement : renderer . domElement ,
99
-
100
- keys : [ 65 , 83 , 68 ]
101
- } ) ;
81
+
82
+ camera = new THREE . PerspectiveCamera ( 40 , window . innerWidth / window . innerHeight , 1 , 1000000 ) ;
102
83
camera . position . z = 5000 ;
103
84
85
+ controls = new THREE . TrackballControls ( camera ) ;
86
+
87
+ controls . rotateSpeed = 0.5 ;
88
+ controls . zoomSpeed = 5.2 ;
89
+ controls . panSpeed = 1 ;
90
+
91
+ controls . noZoom = false ;
92
+ controls . noPan = false ;
93
+
94
+ controls . staticMoving = false ;
95
+ controls . dynamicDampingFactor = 0.3 ;
96
+
97
+ controls . keys = [ 65 , 83 , 68 ] ;
98
+
99
+ controls . addEventListener ( 'change' , render ) ;
100
+
104
101
scene = new THREE . Scene ( ) ;
105
102
106
103
// Node geometry
107
104
if ( that . layout === "3d" ) {
108
- geometry = new THREE . SphereGeometry ( 25 , 25 , 25 ) ;
105
+ geometry = new THREE . CubeGeometry ( 25 , 25 , 25 ) ;
109
106
} else {
110
- geometry = new THREE . SphereGeometry ( 50 , 50 , 0 ) ;
107
+ geometry = new THREE . CubeGeometry ( 50 , 50 , 0 ) ;
111
108
}
112
-
109
+
113
110
// Create node selection, if set
114
111
if ( that . selection ) {
115
112
object_selection = new THREE . ObjectSelection ( {
@@ -128,7 +125,7 @@ Drawing.SimpleGraph = function(options) {
128
125
}
129
126
130
127
document . body . appendChild ( renderer . domElement ) ;
131
-
128
+
132
129
// Stats.js
133
130
if ( that . show_stats ) {
134
131
stats = new Stats ( ) ;
@@ -146,7 +143,7 @@ Drawing.SimpleGraph = function(options) {
146
143
document . body . appendChild ( info ) ;
147
144
}
148
145
}
149
-
146
+
150
147
151
148
/**
152
149
* Creates a graph with random nodes and edges.
@@ -172,7 +169,7 @@ Drawing.SimpleGraph = function(options) {
172
169
var target_node = new Node ( i * steps ) ;
173
170
if ( graph . addNode ( target_node ) ) {
174
171
target_node . data . title = "This is node " + target_node . id ;
175
-
172
+
176
173
drawNode ( target_node ) ;
177
174
nodes . push ( target_node ) ;
178
175
if ( graph . addEdge ( node , target_node ) ) {
@@ -181,8 +178,8 @@ Drawing.SimpleGraph = function(options) {
181
178
}
182
179
}
183
180
steps ++ ;
184
- }
185
-
181
+ }
182
+
186
183
that . layout_options . width = that . layout_options . width || 2000 ;
187
184
that . layout_options . height = that . layout_options . height || 2000 ;
188
185
that . layout_options . iterations = that . layout_options . iterations || 100000 ;
@@ -198,55 +195,56 @@ Drawing.SimpleGraph = function(options) {
198
195
* Create a node object and add it to the scene.
199
196
*/
200
197
function drawNode ( node ) {
201
- var draw_object = new THREE . Mesh ( geometry , [ new THREE . MeshBasicMaterial ( { color : Math . random ( ) * 0xffffff , opacity : 0.5 } ) ] ) ;
202
-
198
+ var draw_object = new THREE . Mesh ( geometry , new THREE . MeshBasicMaterial ( { color : Math . random ( ) * 0xffffff , opacity : 0.5 } ) ) ;
199
+
203
200
if ( that . show_labels ) {
204
201
if ( node . data . title != undefined ) {
205
202
var label_object = new THREE . Label ( node . data . title ) ;
206
203
} else {
207
204
var label_object = new THREE . Label ( node . id ) ;
208
205
}
209
206
node . data . label_object = label_object ;
210
- scene . addObject ( node . data . label_object ) ;
207
+ scene . add ( node . data . label_object ) ;
211
208
}
212
209
213
210
var area = 5000 ;
214
211
draw_object . position . x = Math . floor ( Math . random ( ) * ( area + area + 1 ) - area ) ;
215
212
draw_object . position . y = Math . floor ( Math . random ( ) * ( area + area + 1 ) - area ) ;
216
-
213
+
217
214
if ( that . layout === "3d" ) {
218
215
draw_object . position . z = Math . floor ( Math . random ( ) * ( area + area + 1 ) - area ) ;
219
216
}
220
217
221
218
draw_object . id = node . id ;
222
219
node . data . draw_object = draw_object ;
223
220
node . position = draw_object . position ;
224
- scene . addObject ( node . data . draw_object ) ;
221
+ scene . add ( node . data . draw_object ) ;
225
222
}
226
223
227
224
228
225
/**
229
226
* Create an edge object (line) and add it to the scene.
230
227
*/
231
228
function drawEdge ( source , target ) {
232
- material = new THREE . LineBasicMaterial ( { color : 0xff0000 , opacity : 1 , linewidth : 0.5 } ) ;
229
+ material = new THREE . LineBasicMaterial ( { color : 0xff0000 , opacity : 1 , linewidth : 0.5 } ) ;
230
+
233
231
var tmp_geo = new THREE . Geometry ( ) ;
234
-
235
- tmp_geo . vertices . push ( new THREE . Vertex ( source . data . draw_object . position ) ) ;
236
- tmp_geo . vertices . push ( new THREE . Vertex ( target . data . draw_object . position ) ) ;
232
+ tmp_geo . vertices . push ( source . data . draw_object . position ) ;
233
+ tmp_geo . vertices . push ( target . data . draw_object . position ) ;
237
234
238
235
line = new THREE . Line ( tmp_geo , material , THREE . LinePieces ) ;
239
236
line . scale . x = line . scale . y = line . scale . z = 1 ;
240
237
line . originalScale = 1 ;
241
-
238
+
242
239
geometries . push ( tmp_geo ) ;
243
-
244
- scene . addObject ( line ) ;
240
+
241
+ scene . add ( line ) ;
245
242
}
246
243
247
244
248
245
function animate ( ) {
249
246
requestAnimationFrame ( animate ) ;
247
+ controls . update ( ) ;
250
248
render ( ) ;
251
249
if ( that . show_info ) {
252
250
printInfo ( ) ;
@@ -265,7 +263,7 @@ Drawing.SimpleGraph = function(options) {
265
263
266
264
// Update position of lines (edges)
267
265
for ( var i = 0 ; i < geometries . length ; i ++ ) {
268
- geometries [ i ] . __dirtyVertices = true ;
266
+ geometries [ i ] . verticesNeedUpdate = true ;
269
267
}
270
268
271
269
@@ -287,15 +285,15 @@ Drawing.SimpleGraph = function(options) {
287
285
var label_object = new THREE . Label ( node . id , node . data . draw_object ) ;
288
286
}
289
287
node . data . label_object = label_object ;
290
- scene . addObject ( node . data . label_object ) ;
288
+ scene . add ( node . data . label_object ) ;
291
289
}
292
290
}
293
291
} else {
294
292
var length = graph . nodes . length ;
295
293
for ( var i = 0 ; i < length ; i ++ ) {
296
294
var node = graph . nodes [ i ] ;
297
295
if ( node . data . label_object != undefined ) {
298
- scene . removeObject ( node . data . label_object ) ;
296
+ scene . remove ( node . data . label_object ) ;
299
297
node . data . label_object = undefined ;
300
298
}
301
299
}
@@ -310,7 +308,7 @@ Drawing.SimpleGraph = function(options) {
310
308
if ( that . show_stats ) {
311
309
stats . update ( ) ;
312
310
}
313
-
311
+
314
312
// render scene
315
313
renderer . render ( scene , camera ) ;
316
314
}
@@ -333,9 +331,9 @@ Drawing.SimpleGraph = function(options) {
333
331
function randomFromTo ( from , to ) {
334
332
return Math . floor ( Math . random ( ) * ( to - from + 1 ) + from ) ;
335
333
}
336
-
334
+
337
335
// Stop layout calculation
338
336
this . stop_calculating = function ( ) {
339
337
graph . layout . stop_calculating ( ) ;
340
338
}
341
- }
339
+ }
0 commit comments