@@ -115,8 +115,6 @@ function sankeyModel(layout, d, i) {
115
115
node = sankeyNodes [ n ] ;
116
116
node . width = width ;
117
117
node . height = height ;
118
- if ( node . parallel ) node . x = ( horizontal ? width : height ) * node . parallel ;
119
- if ( node . perpendicular ) node . y = ( horizontal ? height : width ) * node . perpendicular ;
120
118
}
121
119
122
120
switchToForceFormat ( nodes ) ;
@@ -180,9 +178,7 @@ function nodeModel(uniqueKeys, d, n) {
180
178
zoneThicknessPad = c . nodePadAcross ,
181
179
zoneLengthPad = d . nodePad / 2 ,
182
180
visibleThickness = n . dx + 0.5 ,
183
- visibleLength = n . dy - 0.5 ,
184
- zoneThickness = visibleThickness + 2 * zoneThicknessPad ,
185
- zoneLength = visibleLength + 2 * zoneLengthPad ;
181
+ visibleLength = n . dy - 0.5 ;
186
182
187
183
var basicKey = n . label ;
188
184
var foundKey = uniqueKeys [ basicKey ] ;
@@ -198,15 +194,15 @@ function nodeModel(uniqueKeys, d, n) {
198
194
nodeLineWidth : d . nodeLineWidth ,
199
195
textFont : d . textFont ,
200
196
size : d . horizontal ? d . height : d . width ,
201
- visibleWidth : Math . ceil ( d . horizontal ? visibleThickness : visibleLength ) ,
202
- visibleHeight : Math . ceil ( d . horizontal ? visibleLength : visibleThickness ) ,
203
- zoneX : d . horizontal ? - zoneThicknessPad : - zoneLengthPad ,
204
- zoneY : d . horizontal ? - zoneLengthPad : - zoneThicknessPad ,
205
- zoneWidth : d . horizontal ? zoneThickness : zoneLength ,
206
- zoneHeight : d . horizontal ? zoneLength : zoneThickness ,
197
+ visibleWidth : Math . ceil ( visibleThickness ) ,
198
+ visibleHeight : Math . ceil ( visibleLength ) ,
199
+ zoneX : - zoneThicknessPad ,
200
+ zoneY : - zoneLengthPad ,
201
+ zoneWidth : visibleThickness + 2 * zoneThicknessPad ,
202
+ zoneHeight : visibleLength + 2 * zoneLengthPad ,
207
203
labelY : d . horizontal ? n . dy / 2 + 1 : n . dx / 2 + 1 ,
208
204
left : n . originalLayer === 1 ,
209
- sizeAcross : d . horizontal ? d . width : d . height ,
205
+ sizeAcross : d . width ,
210
206
forceLayouts : d . forceLayouts ,
211
207
horizontal : d . horizontal ,
212
208
darkBackground : tc . getBrightness ( ) <= 128 ,
@@ -230,9 +226,7 @@ function crispLinesOnEnd(sankeyNode) {
230
226
function updateNodePositions ( sankeyNode ) {
231
227
sankeyNode
232
228
. attr ( 'transform' , function ( d ) {
233
- return d . horizontal ?
234
- 'translate(' + ( d . node . x - 0.5 ) + ', ' + ( d . node . y - d . node . dy / 2 + 0.5 ) + ')' :
235
- 'translate(' + ( d . node . y - d . node . dy / 2 - 0.5 ) + ', ' + ( d . node . x + 0.5 ) + ')' ;
229
+ return 'translate(' + ( d . node . x - 0.5 ) + ', ' + ( d . node . y - d . node . dy / 2 + 0.5 ) + ')' ;
236
230
} ) ;
237
231
}
238
232
@@ -259,20 +253,28 @@ function sizeNode(rect) {
259
253
. attr ( 'height' , function ( d ) { return d . visibleHeight ; } ) ;
260
254
}
261
255
262
- function salientEnough ( d ) {
263
- return d . link . dy > 1 || d . linkLineWidth > 0 ;
256
+ function salientEnough ( d ) { return d . link . dy > 1 || d . linkLineWidth > 0 ; }
257
+
258
+ function sankeyTransform ( d ) {
259
+ var offset = 'translate(' + d . translateX + ',' + d . translateY + ')' ;
260
+ return offset + ( d . horizontal ? 'matrix(1 0 0 1 0 0)' : 'matrix(0 1 1 0 0 0)' ) ;
264
261
}
265
262
266
- function linksTransform ( d ) {
267
- return d . horizontal ? 'matrix(1 0 0 1 0 0)' : 'matrix(0 1 1 0 0 0 )';
263
+ function nodeCentering ( d ) {
264
+ return 'translate(' + ( d . horizontal ? 0 : d . labelY ) + ' ' + ( d . horizontal ? d . labelY : 0 ) + ' )';
268
265
}
269
266
270
267
function textGuidePath ( d ) {
271
268
return d3 . svg . line ( ) ( [
272
- [ d . horizontal ? ( d . left ? - d . sizeAcross : d . visibleWidth + c . nodeTextOffsetHorizontal ) : c . nodeTextOffsetHorizontal , d . labelY ] ,
273
- [ d . horizontal ? ( d . left ? - c . nodeTextOffsetHorizontal : d . sizeAcross ) : d . visibleWidth - c . nodeTextOffsetHorizontal , d . labelY ]
269
+ [ d . horizontal ? ( d . left ? - d . sizeAcross : d . visibleWidth + c . nodeTextOffsetHorizontal ) : c . nodeTextOffsetHorizontal , 0 ] ,
270
+ [ d . horizontal ? ( d . left ? - c . nodeTextOffsetHorizontal : d . sizeAcross ) : d . visibleHeight - c . nodeTextOffsetHorizontal , 0 ]
274
271
] ) ; }
275
272
273
+ function sankeyInverseTransform ( d ) { return d . horizontal ? 'matrix(1 0 0 1 0 0)' : 'matrix(0 1 1 0 0 0)' ; }
274
+ function textFlip ( d ) { return d . horizontal ? 'scale(1 1)' : 'scale(-1 1)' ; }
275
+ function nodeTextColor ( d ) { return d . darkBackground && ! d . horizontal ? 'rgb(255,255,255)' : 'rgb(0,0,0)' ; }
276
+ function nodeTextOffset ( d ) { return d . horizontal && d . left ? '100%' : '0%' ; }
277
+
276
278
// event handling
277
279
278
280
function attachPointerEvents ( selection , sankey , eventSet ) {
@@ -311,7 +313,7 @@ function attachDragHandler(sankeyNode, sankeyLink, callbacks) {
311
313
312
314
var dragBehavior = d3 . behavior . drag ( )
313
315
314
- . origin ( function ( d ) { return d . horizontal ? d . node : { x : d . node . y , y : d . node . x } ; } )
316
+ . origin ( function ( d ) { return d . node ; } )
315
317
316
318
. on ( 'dragstart' , function ( d ) {
317
319
if ( d . arrangement === 'fixed' ) return ;
@@ -335,8 +337,8 @@ function attachDragHandler(sankeyNode, sankeyLink, callbacks) {
335
337
336
338
. on ( 'drag' , function ( d ) {
337
339
if ( d . arrangement === 'fixed' ) return ;
338
- var x = d . horizontal ? d3 . event . x : d3 . event . y ;
339
- var y = d . horizontal ? d3 . event . y : d3 . event . x ;
340
+ var x = d3 . event . x ;
341
+ var y = d3 . event . y ;
340
342
if ( d . arrangement === 'snap' ) {
341
343
d . node . x = x ;
342
344
d . node . y = y ;
@@ -432,23 +434,20 @@ module.exports = function(svg, styledData, layout, callbacks) {
432
434
. style ( 'left' , 0 )
433
435
. style ( 'shape-rendering' , 'geometricPrecision' )
434
436
. style ( 'pointer-events' , 'auto' )
435
- . style ( 'box-sizing' , 'content-box' ) ;
437
+ . style ( 'box-sizing' , 'content-box' )
438
+ . attr ( 'transform' , sankeyTransform ) ;
436
439
437
- sankey
438
- . attr ( 'transform' , function ( d ) { return 'translate(' + d . translateX + ',' + d . translateY + ')' ; } ) ;
440
+ sankey . transition ( )
441
+ . ease ( c . ease ) . duration ( c . duration )
442
+ . attr ( 'transform' , sankeyTransform ) ;
439
443
440
444
var sankeyLinks = sankey . selectAll ( '.sankeyLinks' )
441
445
. data ( repeat , keyFun ) ;
442
446
443
447
sankeyLinks . enter ( )
444
448
. append ( 'g' )
445
449
. classed ( 'sankeyLinks' , true )
446
- . style ( 'fill' , 'none' )
447
- . attr ( 'transform' , linksTransform ) ;
448
-
449
- sankeyLinks . transition ( )
450
- . ease ( c . ease ) . duration ( c . duration )
451
- . attr ( 'transform' , linksTransform ) ;
450
+ . style ( 'fill' , 'none' ) ;
452
451
453
452
var sankeyLink = sankeyLinks . selectAll ( '.sankeyLink' )
454
453
. data ( function ( d ) {
@@ -562,26 +561,42 @@ module.exports = function(svg, styledData, layout, callbacks) {
562
561
. attr ( 'width' , function ( d ) { return d . zoneWidth ; } )
563
562
. attr ( 'height' , function ( d ) { return d . zoneHeight ; } ) ;
564
563
565
- var nodeLabelGuide = sankeyNode . selectAll ( '.nodeLabelGuide' )
564
+ var nodeCentered = sankeyNode . selectAll ( '.nodeCentered' )
565
+ . data ( repeat ) ;
566
+
567
+ nodeCentered . enter ( )
568
+ . append ( 'g' )
569
+ . classed ( 'nodeCentered' , true )
570
+ . attr ( 'transform' , nodeCentering ) ;
571
+
572
+ nodeCentered
573
+ . transition ( )
574
+ . ease ( c . ease ) . duration ( c . duration )
575
+ . attr ( 'transform' , nodeCentering ) ;
576
+
577
+ var nodeLabelGuide = nodeCentered . selectAll ( '.nodeLabelGuide' )
566
578
. data ( repeat ) ;
567
579
568
580
nodeLabelGuide . enter ( )
569
581
. append ( 'path' )
570
582
. classed ( 'nodeLabelGuide' , true )
571
583
. attr ( 'id' , function ( d ) { return d . uniqueNodeLabelPathId ; } )
572
- . attr ( 'd' , textGuidePath ) ;
584
+ . attr ( 'd' , textGuidePath )
585
+ . attr ( 'transform' , sankeyInverseTransform ) ;
573
586
574
587
nodeLabelGuide
575
588
. transition ( )
576
589
. ease ( c . ease ) . duration ( c . duration )
577
- . attr ( 'd' , textGuidePath ) ;
590
+ . attr ( 'd' , textGuidePath )
591
+ . attr ( 'transform' , sankeyInverseTransform ) ;
578
592
579
- var nodeLabel = sankeyNode . selectAll ( '.nodeLabel' )
593
+ var nodeLabel = nodeCentered . selectAll ( '.nodeLabel' )
580
594
. data ( repeat ) ;
581
595
582
596
nodeLabel . enter ( )
583
597
. append ( 'text' )
584
598
. classed ( 'nodeLabel' , true )
599
+ . attr ( 'transform' , textFlip )
585
600
. style ( 'user-select' , 'none' )
586
601
. style ( 'cursor' , 'default' )
587
602
. style ( 'fill' , 'black' ) ;
@@ -592,18 +607,29 @@ module.exports = function(svg, styledData, layout, callbacks) {
592
607
} )
593
608
. each ( function ( d ) { Drawing . font ( nodeLabel , d . textFont ) ; } ) ;
594
609
610
+ nodeLabel
611
+ . transition ( )
612
+ . ease ( c . ease ) . duration ( c . duration )
613
+ . attr ( 'transform' , textFlip ) ;
614
+
595
615
var nodeLabelTextPath = nodeLabel . selectAll ( '.nodeLabelTextPath' )
596
616
. data ( repeat ) ;
597
617
598
618
nodeLabelTextPath . enter ( )
599
619
. append ( 'textPath' )
600
620
. classed ( 'nodeLabelTextPath' , true )
601
621
. attr ( 'alignment-baseline' , 'middle' )
602
- . attr ( 'xlink:href' , function ( d ) { return '#' + d . uniqueNodeLabelPathId ; } ) ;
622
+ . attr ( 'xlink:href' , function ( d ) { return '#' + d . uniqueNodeLabelPathId ; } )
623
+ . attr ( 'startOffset' , nodeTextOffset )
624
+ . style ( 'fill' , nodeTextColor ) ;
603
625
604
626
nodeLabelTextPath
605
627
. text ( function ( d ) { return d . horizontal || d . node . dy > 5 ? d . node . label : '' ; } )
606
- . attr ( 'startOffset' , function ( d ) { return d . horizontal && d . left ? '100%' : '0%' ; } )
607
- . style ( 'text-anchor' , function ( d ) { return d . horizontal && d . left ? 'end' : 'start' ; } )
608
- . style ( 'fill' , function ( d ) { return d . darkBackground && ! d . horizontal ? 'white' : 'black' ; } ) ;
628
+ . style ( 'text-anchor' , function ( d ) { return d . horizontal && d . left ? 'end' : 'start' ; } ) ;
629
+
630
+ nodeLabelTextPath
631
+ . transition ( )
632
+ . ease ( c . ease ) . duration ( c . duration )
633
+ . attr ( 'startOffset' , nodeTextOffset )
634
+ . style ( 'fill' , nodeTextColor ) ;
609
635
} ;
0 commit comments