Skip to content

Commit be1acc8

Browse files
committed
initial rough integration of d3-sankey-circular
1 parent 5418d25 commit be1acc8

File tree

6 files changed

+91
-45
lines changed

6 files changed

+91
-45
lines changed

package-lock.json

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
"country-regex": "^1.1.0",
6666
"d3": "^3.5.12",
6767
"d3-sankey": "git://github.com/antoinerg/d3-sankey.git#4f37ed8d3578b545a8569ecd74583f373768e900",
68+
"d3-sankey-circular": "^0.26.0",
6869
"d3-array": "1",
6970
"d3-collection": "1",
7071
"d3-force": "^1.0.6",

src/traces/sankey/calc.js

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,8 @@ function circularityPresent(nodeList, sources, targets) {
3939

4040
module.exports = function calc(gd, trace) {
4141

42-
if(circularityPresent(trace.node.label, trace.link.source, trace.link.target)) {
43-
Lib.error('Circularity is present in the Sankey data. Removing all nodes and links.');
44-
trace.link.label = [];
45-
trace.link.source = [];
46-
trace.link.target = [];
47-
trace.link.value = [];
48-
trace.link.color = [];
49-
trace.node.label = [];
50-
trace.node.color = [];
42+
if(!circularityPresent(trace.node.label, trace.link.source, trace.link.target)) {
43+
// TODO: swap to original sankey engine
5144
}
5245

5346
var result = convertToD3Sankey(trace);

src/traces/sankey/render.js

Lines changed: 48 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,16 @@ var d3 = require('d3');
1313
var tinycolor = require('tinycolor2');
1414
var Color = require('../../components/color');
1515
var Drawing = require('../../components/drawing');
16-
var d3sankey = require('d3-sankey');
16+
// TODO: allow swapping Sankey engine
17+
// var d3Sankey = require('d3-sankey');
18+
var d3SankeyCircular = require('d3-sankey-circular');
1719
var d3Force = require('d3-force');
1820
var Lib = require('../../lib');
1921
var gup = require('../../lib/gup');
2022
var keyFun = gup.keyFun;
2123
var repeat = gup.repeat;
2224
var unwrap = gup.unwrap;
23-
var interpolateNumber = require('d3-interpolate').interpolateNumber;
25+
// var interpolateNumber = require('d3-interpolate').interpolateNumber;
2426

2527
// view models
2628

@@ -38,12 +40,13 @@ function sankeyModel(layout, d, traceIndex) {
3840
var nodes = calcData._nodes;
3941
var links = calcData._links;
4042

41-
var sankey = d3sankey
42-
.sankey()
43+
var sankey = d3SankeyCircular
44+
.sankeyCircular()
4345
.iterations(c.sankeyIterations)
4446
.size(horizontal ? [width, height] : [height, width])
4547
.nodeWidth(nodeThickness)
4648
.nodePadding(nodePad)
49+
.circularLinkGap(2)
4750
.nodes(nodes)
4851
.links(links);
4952

@@ -108,29 +111,34 @@ function linkModel(d, l, i) {
108111
}
109112

110113
function linkPath() {
111-
var curvature = 0.5;
112-
113-
function shape(d) {
114-
var x0 = d.link.source.x1,
115-
x1 = d.link.target.x0,
116-
xi = interpolateNumber(x0, x1),
117-
x2 = xi(curvature),
118-
x3 = xi(1 - curvature),
119-
y0a = d.link.y0 - d.link.width / 2,
120-
y0b = d.link.y0 + d.link.width / 2,
121-
y1a = d.link.y1 - d.link.width / 2,
122-
y1b = d.link.y1 + d.link.width / 2;
123-
return 'M' + x0 + ',' + y0a +
124-
'C' + x2 + ',' + y0a +
125-
' ' + x3 + ',' + y1a +
126-
' ' + x1 + ',' + y1a +
127-
'L' + x1 + ',' + y1b +
128-
'C' + x3 + ',' + y1b +
129-
' ' + x2 + ',' + y0b +
130-
' ' + x0 + ',' + y0b +
131-
'Z';
114+
function circular(d) {
115+
return d.link.path;
132116
}
133-
return shape;
117+
118+
return circular;
119+
// var curvature = 0.5;
120+
121+
// function shape(d) {
122+
// var x0 = d.link.source.x1,
123+
// x1 = d.link.target.x0,
124+
// xi = interpolateNumber(x0, x1),
125+
// x2 = xi(curvature),
126+
// x3 = xi(1 - curvature),
127+
// y0a = d.link.y0 - d.link.width / 2,
128+
// y0b = d.link.y0 + d.link.width / 2,
129+
// y1a = d.link.y1 - d.link.width / 2,
130+
// y1b = d.link.y1 + d.link.width / 2;
131+
// return 'M' + x0 + ',' + y0a +
132+
// 'C' + x2 + ',' + y0a +
133+
// ' ' + x3 + ',' + y1a +
134+
// ' ' + x1 + ',' + y1a +
135+
// 'L' + x1 + ',' + y1b +
136+
// 'C' + x3 + ',' + y1b +
137+
// ' ' + x2 + ',' + y0b +
138+
// ' ' + x0 + ',' + y0b +
139+
// 'Z';
140+
// }
141+
// return shape;
134142
}
135143

136144
function nodeModel(d, n, i) {
@@ -177,7 +185,7 @@ function nodeModel(d, n, i) {
177185
valueFormat: d.valueFormat,
178186
valueSuffix: d.valueSuffix,
179187
sankey: d.sankey,
180-
graph: d.sankey(),
188+
graph: d.sankey.graph,
181189
arrangement: d.arrangement,
182190
uniqueNodeLabelPathId: [d.guid, d.key, key].join('_'),
183191
interactionState: d.interactionState
@@ -466,7 +474,8 @@ module.exports = function(svg, calcData, layout, callbacks) {
466474

467475
var sankeyLink = sankeyLinks.selectAll('.' + c.cn.sankeyLink)
468476
.data(function(d) {
469-
return d.sankey().links
477+
var links = d.graph.links;
478+
return links
470479
.filter(function(l) {return l.value;})
471480
.map(linkModel.bind(null, d));
472481
}, keyFun);
@@ -479,14 +488,17 @@ module.exports = function(svg, calcData, layout, callbacks) {
479488

480489
sankeyLink
481490
.style('stroke', function(d) {
482-
return salientEnough(d) ? Color.tinyRGB(tinycolor(d.linkLineColor)) : d.tinyColorHue;
491+
return d.tinyColorHue;
492+
// return salientEnough(d) ? Color.tinyRGB(tinycolor(d.linkLineColor)) : d.tinyColorHue;
483493
})
484494
.style('stroke-opacity', function(d) {
485-
return salientEnough(d) ? Color.opacity(d.linkLineColor) : d.tinyColorAlpha;
495+
return d.tinyColorAlpha;
496+
// return salientEnough(d) ? Color.opacity(d.linkLineColor) : d.tinyColorAlpha;
486497
})
487-
.style('stroke-width', function(d) {return salientEnough(d) ? d.linkLineWidth : 1;})
488-
.style('fill', function(d) {return d.tinyColorHue;})
489-
.style('fill-opacity', function(d) {return d.tinyColorAlpha;});
498+
// .style('stroke-width', function(d) {return salientEnough(d) ? d.linkLineWidth : 1;})
499+
//.style('fill', function(d) {return d.link.color;})
500+
//.style('fill-opacity', function(d) {return d.tinyColorAlpha;})
501+
.style('stroke-width', function(d) {return d.link.width;});
490502

491503
sankeyLink.transition()
492504
.ease(c.ease).duration(c.duration)
@@ -515,7 +527,7 @@ module.exports = function(svg, calcData, layout, callbacks) {
515527

516528
var sankeyNode = sankeyNodeSet.selectAll('.' + c.cn.sankeyNode)
517529
.data(function(d) {
518-
var nodes = d.sankey().nodes;
530+
var nodes = d.graph.nodes;
519531
persistOriginalPlace(nodes);
520532
return nodes
521533
.filter(function(n) {return n.value;})
@@ -528,8 +540,8 @@ module.exports = function(svg, calcData, layout, callbacks) {
528540
.call(updateNodePositions)
529541
.call(attachPointerEvents, sankey, callbacks.nodeEvents);
530542

531-
sankeyNode
532-
.call(attachDragHandler, sankeyLink, callbacks); // has to be here as it binds sankeyLink
543+
// sankeyNode
544+
// .call(attachDragHandler, sankeyLink, callbacks); // has to be here as it binds sankeyLink
533545

534546
sankeyNode.transition()
535547
.ease(c.ease).duration(c.duration)
32 KB
Loading

test/image/mocks/sankey_circular.json

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"data": [
3+
{
4+
"type": "sankey",
5+
"node": {
6+
"pad": 1,
7+
"label": ["0", "1", "2", "3", "4", "5"]
8+
},
9+
"link": {
10+
"source": [
11+
0, 0, 1, 2, 5, 4, 3
12+
],
13+
"target": [
14+
5, 3, 4, 3, 0, 2, 2
15+
],
16+
"value": [
17+
1, 2, 1, 1, 1, 1, 1
18+
],
19+
"label": ["1", "2", "3", "4", "5"]
20+
}
21+
}],
22+
"layout": {
23+
"title": "Sankey with circular data",
24+
"margin": {
25+
"l": 25, "r": 25, "t": 25, "b": 25
26+
},
27+
"width": 800,
28+
"height": 800
29+
}
30+
}

0 commit comments

Comments
 (0)