@@ -52,24 +52,54 @@ var max = d3array.max;
52
52
var nest = require ( 'd3-collection' ) . nest ;
53
53
var interpolateNumber = require ( 'd3-interpolate' ) . interpolateNumber ;
54
54
55
+ // sort links' breadth (ie top to bottom in a column), based on their source nodes' breadths
56
+ function ascendingSourceDepth ( a , b ) {
57
+ return ascendingBreadth ( a . source , b . source ) || ( a . originalIndex - b . originalIndex ) ;
58
+ }
59
+
60
+ // sort links' breadth (ie top to bottom in a column), based on their target nodes' breadths
61
+ function ascendingTargetDepth ( a , b ) {
62
+ return ascendingBreadth ( a . target , b . target ) || ( a . originalIndex - b . originalIndex ) ;
63
+ }
64
+
65
+ function ascendingBreadth ( a , b ) {
66
+ return a . y - b . y ;
67
+ }
68
+
69
+ function value ( d ) {
70
+ return d . value ;
71
+ }
72
+
73
+ function nodeCenter ( node ) {
74
+ return node . y + node . dy / 2 ;
75
+ }
76
+
77
+ function weightedSource ( link ) {
78
+ return nodeCenter ( link . source ) * link . value ;
79
+ }
80
+
81
+ function weightedTarget ( link ) {
82
+ return nodeCenter ( link . target ) * link . value ;
83
+ }
84
+
55
85
module . exports = function ( ) {
56
86
var sankey = { } ,
57
- nodeWidth = 24 ,
58
- nodePadding = 8 ,
87
+ dx = 24 , // nodeWidth
88
+ py = 8 , // nodePadding
59
89
size = [ 1 , 1 ] ,
60
90
nodes = [ ] ,
61
91
links = [ ] ,
62
92
maxPaddedSpace = 2 / 3 ; // Defined as a fraction of the total available space
63
93
64
94
sankey . nodeWidth = function ( _ ) {
65
- if ( ! arguments . length ) return nodeWidth ;
66
- nodeWidth = + _ ;
95
+ if ( ! arguments . length ) return dx ;
96
+ dx = + _ ;
67
97
return sankey ;
68
98
} ;
69
99
70
100
sankey . nodePadding = function ( _ ) {
71
- if ( ! arguments . length ) return nodePadding ;
72
- nodePadding = + _ ;
101
+ if ( ! arguments . length ) return py ;
102
+ py = + _ ;
73
103
return sankey ;
74
104
} ;
75
105
@@ -94,14 +124,14 @@ module.exports = function() {
94
124
sankey . layout = function ( iterations ) {
95
125
computeNodeLinks ( ) ;
96
126
computeNodeValues ( ) ;
97
- computeNodeBreadths ( ) ;
98
- computeNodeDepths ( iterations ) ;
99
- computeLinkDepths ( ) ;
127
+ computeNodeDepths ( ) ;
128
+ computeNodeBreadths ( iterations ) ;
129
+ computeLinkBreadths ( ) ;
100
130
return sankey ;
101
131
} ;
102
132
103
133
sankey . relayout = function ( ) {
104
- computeLinkDepths ( ) ;
134
+ computeLinkBreadths ( ) ;
105
135
return sankey ;
106
136
} ;
107
137
@@ -170,14 +200,15 @@ module.exports = function() {
170
200
// Nodes are assigned the maximum breadth of incoming neighbors plus one;
171
201
// nodes with no incoming links are assigned breadth zero, while
172
202
// nodes with no outgoing links are assigned the maximum breadth.
173
- function computeNodeBreadths ( ) {
203
+ function computeNodeDepths ( ) {
174
204
var remainingNodes = nodes ,
175
205
nextNodes ,
176
206
x = 0 ;
177
207
178
208
function processNode ( node ) {
209
+ node . depth = x ;
179
210
node . x = x ;
180
- node . dx = nodeWidth ;
211
+ node . dx = dx ;
181
212
node . sourceLinks . forEach ( function ( link ) {
182
213
if ( nextNodes . indexOf ( link . target ) < 0 ) {
183
214
nextNodes . push ( link . target ) ;
@@ -194,7 +225,7 @@ module.exports = function() {
194
225
195
226
//
196
227
moveSinksRight ( x ) ;
197
- scaleNodeBreadths ( ( size [ 0 ] - nodeWidth ) / ( x - 1 ) ) ;
228
+ scaleNodeBreadths ( ( size [ 0 ] - dx ) / ( x - 1 ) ) ;
198
229
}
199
230
200
231
// function moveSourcesRight() {
@@ -208,6 +239,7 @@ module.exports = function() {
208
239
function moveSinksRight ( x ) {
209
240
nodes . forEach ( function ( node ) {
210
241
if ( ! node . sourceLinks . length ) {
242
+ node . depth = x - 1 ;
211
243
node . x = x - 1 ;
212
244
}
213
245
} ) ;
@@ -219,7 +251,7 @@ module.exports = function() {
219
251
} ) ;
220
252
}
221
253
222
- function computeNodeDepths ( iterations ) {
254
+ function computeNodeBreadths ( iterations ) {
223
255
var nodesByBreadth = nest ( )
224
256
. key ( function ( d ) { return d . x ; } )
225
257
. sortKeys ( ascending )
@@ -241,9 +273,9 @@ module.exports = function() {
241
273
return nodes . length ;
242
274
} ) ;
243
275
var maxNodePadding = maxPaddedSpace * size [ 1 ] / ( L - 1 ) ;
244
- if ( nodePadding > maxNodePadding ) nodePadding = maxNodePadding ;
276
+ if ( py > maxNodePadding ) py = maxNodePadding ;
245
277
var ky = min ( nodesByBreadth , function ( nodes ) {
246
- return ( size [ 1 ] - ( nodes . length - 1 ) * nodePadding ) / sum ( nodes , value ) ;
278
+ return ( size [ 1 ] - ( nodes . length - 1 ) * py ) / sum ( nodes , value ) ;
247
279
} ) ;
248
280
249
281
nodesByBreadth . forEach ( function ( nodes ) {
@@ -263,29 +295,21 @@ module.exports = function() {
263
295
nodes . forEach ( function ( node ) {
264
296
if ( node . targetLinks . length ) {
265
297
var y = sum ( node . targetLinks , weightedSource ) / sum ( node . targetLinks , value ) ;
266
- node . y += ( y - center ( node ) ) * alpha ;
298
+ node . y += ( y - nodeCenter ( node ) ) * alpha ;
267
299
}
268
300
} ) ;
269
301
} ) ;
270
-
271
- function weightedSource ( link ) {
272
- return center ( link . source ) * link . value ;
273
- }
274
302
}
275
303
276
304
function relaxRightToLeft ( alpha ) {
277
305
nodesByBreadth . slice ( ) . reverse ( ) . forEach ( function ( nodes ) {
278
306
nodes . forEach ( function ( node ) {
279
307
if ( node . sourceLinks . length ) {
280
308
var y = sum ( node . sourceLinks , weightedTarget ) / sum ( node . sourceLinks , value ) ;
281
- node . y += ( y - center ( node ) ) * alpha ;
309
+ node . y += ( y - nodeCenter ( node ) ) * alpha ;
282
310
}
283
311
} ) ;
284
312
} ) ;
285
-
286
- function weightedTarget ( link ) {
287
- return center ( link . target ) * link . value ;
288
- }
289
313
}
290
314
291
315
function resolveCollisions ( ) {
@@ -302,18 +326,18 @@ module.exports = function() {
302
326
node = nodes [ i ] ;
303
327
dy = y0 - node . y ;
304
328
if ( dy > 0 ) node . y += dy ;
305
- y0 = node . y + node . dy + nodePadding ;
329
+ y0 = node . y + node . dy + py ;
306
330
}
307
331
308
332
// If the bottommost node goes outside the bounds, push it back up.
309
- dy = y0 - nodePadding - size [ 1 ] ;
333
+ dy = y0 - py - size [ 1 ] ;
310
334
if ( dy > 0 ) {
311
335
y0 = node . y -= dy ;
312
336
313
337
// Push any overlapping nodes back up.
314
338
for ( i = n - 2 ; i >= 0 ; -- i ) {
315
339
node = nodes [ i ] ;
316
- dy = node . y + node . dy + nodePadding - y0 ;
340
+ dy = node . y + node . dy + py - y0 ;
317
341
if ( dy > 0 ) node . y -= dy ;
318
342
y0 = node . y ;
319
343
}
@@ -326,7 +350,7 @@ module.exports = function() {
326
350
}
327
351
}
328
352
329
- function computeLinkDepths ( ) {
353
+ function computeLinkBreadths ( ) {
330
354
nodes . forEach ( function ( node ) {
331
355
node . sourceLinks . sort ( ascendingTargetDepth ) ;
332
356
node . targetLinks . sort ( ascendingSourceDepth ) ;
@@ -342,22 +366,6 @@ module.exports = function() {
342
366
ty += link . dy ;
343
367
} ) ;
344
368
} ) ;
345
-
346
- function ascendingSourceDepth ( a , b ) {
347
- return ( a . source . y - b . source . y ) || ( a . originalIndex - b . originalIndex ) ;
348
- }
349
-
350
- function ascendingTargetDepth ( a , b ) {
351
- return ( a . target . y - b . target . y ) || ( a . originalIndex - b . originalIndex ) ;
352
- }
353
- }
354
-
355
- function center ( node ) {
356
- return node . y + node . dy / 2 ;
357
- }
358
-
359
- function value ( link ) {
360
- return link . value ;
361
369
}
362
370
363
371
return sankey ;
0 commit comments