0

I am using D3.js to produce Sankey diagrams, and I'm not satisfied with the resulting connection between nodes, particularly when the total input of a node is different from its total output.

As an example:

// set the dimensions and margins of the data
var margin = { top: 10, right: 10, bottom: 10, left: 10 },
    width = 300 - margin.left - margin.right,
    height = 300 - margin.top - margin.bottom;

// append the svg object to the body of the page
var svg = d3.select("#graph").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
    .append("g")
    .attr("transform",
        "translate(" + margin.left + "," + margin.top + ")");

// Set the sankey diagram properties
var sankey = d3.sankey()
    .nodeWidth(10)
    .nodePadding(10)
    .size([width, height]);

data = {
    "nodes": [
        { "node": 0, "name": "A" },
        { "node": 1, "name": "B" },
        { "node": 2, "name": "C" }
    ],
    "links": [
        { "source": 0, "target": 1, "value": 2 },
        { "source": 1, "target": 2, "value": 1 }
    ]
}

// Constructs a new Sankey generator with the default settings.
sankey
    .nodes(data.nodes)
    .links(data.links)
    .layout(1);

// add in the links
svg.append("g")
    .selectAll(".link")
    .data(data.links)
    .enter()
    .append("path")
    .attr("class", "link")
    .attr("d", sankey.link())
    .style("stroke-width", function (d) { return Math.max(1, d.dy); })

// add in the nodes
var node = svg.append("g")
    .selectAll(".node")
    .data(data.nodes)
    .enter()
    .append("g")
    .attr("class", "node")
    .attr("transform", function (d) { return "translate(" + d.x + "," + d.y + ")"; })
    
// add the rectangles for the nodes
node.append("rect")
    .attr("height", function (d) { return d.dy; })
    .attr("width", sankey.nodeWidth())

// add in the title for the nodes
node.append("text")
    .attr("x", -6)
    .attr("y", function (d) { return d.dy / 2; })
    .attr("dy", ".35em")
    .attr("text-anchor", "end")
    .attr("transform", null)
    .text(function (d) { return d.name; })
    .filter(function (d) { return d.x < width / 2; })
    .attr("x", 6 + sankey.nodeWidth())
    .attr("text-anchor", "start")
<body>
    <style>
        .link {
            fill: none;
            stroke: #000;
            stroke-opacity: .2;
        }
    </style>

    <div id="graph"></div>

    <script src="https://d3js.org/d3.v4.min.js"></script>
    <script src="https://cdn.jsdelivr.net/gh/holtzy/D3-graph-gallery@master/LIB/sankey.js"></script>
    <script src="test.js"></script>
</body>

This produces:

A sankey diagram as an example

But without chaning the input data I would like:

A second sankey diagram

Meaning the node size is determined by the link value, but the link size matches both the input and the output nodes.

rikyeah
  • 1,896
  • 4
  • 11
  • 21
  • 1
    Sankey diagrams show the flow of resources. From A to B, flow is one to one, and from B only half goes to C. So your requirement is that from B to C, resource flow becomes half on the way. I think Sankey will not allow you to do so, as it can only represent proportion which went as a flow. – B Kalra Dec 23 '22 at 17:39
  • Yes I understand I am really stretching the use of this type of diagram, I just wanted to know if there is some resource that allows to have this variation – rikyeah Dec 24 '22 at 00:01

0 Answers0