kurkle / chartjs-chart-sankey

Chart.js module for creating sankey diagrams
MIT License
152 stars 29 forks source link

Is it possible to do loops? #24

Open Eric-oktagon opened 3 years ago

Eric-oktagon commented 3 years ago

I am trying to do loops, like { from:"A", to:"B", flow:20 }, { from:"B", to:"B", flow:10 }

but I'm not getting it, am I doing something wrong or still not supported loops?

kurkle commented 3 years ago

Direct loops are not currently possible

simevo commented 3 years ago

When I try this, the CPU fan starts to spin, after a while I get Maximum call stack size exceeded in the console and the chart is not drawn

I have patched the nodeCountfunction like this:

const nodeCount = (list, prop) => {
  return list.reduce((acc, cur) => {
    if (cur.node[prop] === list) {
      return acc + cur.node[prop].length;
    } else {
      return acc + cur.node[prop].length + nodeCount(cur.node[prop], prop);
    }
  }, 0);
}

and now the loop is not shown but a vertical length of the node "bar" is reserved for it: image

here is the test file I am using in the build dir:

<!DOCTYPE html>
<html lang="">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title>Sankey</title>
    <style>
      .chart {
        max-width: 800px;
        max-height: 600px;
      }
    </style>
  </head>
  <body>
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    <script src="dist/chartjs-chart-sankey.js"></script>

    <div class="chart">
      <canvas id="chart"></canvas>
    </div>
    <script>
      var ctx = document.getElementById("chart").getContext("2d");

      var colors = {
        A: 'red',
        B: 'blue'
      }

      function getColor(name) {
        return colors[name] || "green";
      }

      var chart = new Chart(ctx, {
        type: "sankey",
        data: {
          datasets: [
            {
              data: [
              { from:"A", to:"B", flow:20 },
              { from:"B", to:"B", flow:10 }
              ],
              colorFrom: (c) => getColor(c.dataset.data[c.dataIndex].from),
              colorTo: (c) => getColor(c.dataset.data[c.dataIndex].to),
              borderWidth: 2,
              borderColor: 'black'
            }
          ]
        }
      });
      </script>
  </body>
</html>

can you give me a hint how to make it draw the loop ? I'd send a PR if you wish, thanks