Chart.js module for creating sankey diagrams

Overview

chartjs-chart-sankey

Chart.js v3.3.x module for creating sankey diagrams

npm pre-release Node.js CI npm bundle size GitHub

Browser support

All modern and up-to-date browsers are supported, including, but not limited to:

  • Chrome
  • Edge
  • Firefox
  • Safari

Internet Explorer 11 is not supported.

Typescript

Typescript 3.x and higher is supported.

Documentation

You can use chartjs-chart-sankey.js as ES module. You'll need to manually register two components

import {Chart} from 'chart.js';
import {SankeyController, Flow} from 'chartjs-chart-sankey';

Chart.register(SankeyController, Flow);

To create a sankey chart, include chartjs-chart-sankey.js after chart.js and then create the chart by setting the type attribute to 'sankey'

const chart = new Chart(ctx, {
  type: 'sankey',
  data: dataObject
});

Configuration

Example:

const chart = new Chart(ctx, {
  type: 'sankey',
  data: {
    datasets: [{
      label: 'My sankey',
      data: [
        {from: 'a', to: 'b', flow: 10},
        {from: 'a', to: 'c', flow: 5},
        {from: 'b', to: 'c', flow: 10}
      ],
      colorFrom: (c) => getColor(c.dataset.data[c.dataIndex].from),
      colorTo: (c) => getColor(c.dataset.data[c.dataIndex].to),
      colorMode: 'gradient', // or 'from' or 'to'
      /* optional labels */
      labels: {
        a: 'Label A',
        b: 'Label B',
        c: 'Label C'
      },
      /* optional priority */
      priority: {
        a: 0,
        b: 1,
        c: 2
      },
      size: 'max', // or 'min' if flow overlap is preferred
    }]
  },
});

Example

Sankey Example Image

Online examples

codepen Vue.js 2

Development

You first need to install node dependencies (requires Node.js):

> npm install

The following commands will then be available from the repository root:

> npm run build         // build dist files
> npm run autobuild     // build and watch for changes
> npm test              // run all tests
> npm autotest          // run all tests and watch for changes
> npm lint              // perform code linting
> npm package           // create an archive with dist files and samples

License

chartjs-chart-sankey is available under the MIT license.

Comments
  • Changing stack order

    Changing stack order

    Hi,

    is there a possibility to force a custom stack ordering at a vertical bar group? For example: Set an priority index within a dataset property property? Like this (with the result, that "Oil" is on top, middle "Coal", bottom "Natural Gas" in the left bar. With highest priority number is on top.): Unbenannt


    Currently the element with the highest value is at the top.

    Btw: Very cool library. Good work.

    enhancement 
    opened by dpanster 8
  • Uncaught RangeError: Maximum call stack size exceeded

    Uncaught RangeError: Maximum call stack size exceeded

    When I using this array of data:

    const chartDataTest = [ { from: 'User1', to: 'User2', flow: 23.67 }, { from: 'User1', to: 'User3', flow: 25.33 }, { from: 'User1', to: 'User4', flow: 41 }, { from: 'User1', to: 'User5', flow: 31.33 }, { from: 'User1', to: 'User6', flow: 11.33 }, { from: 'User1', to: 'User7', flow: 15.13 }, { from: 'User1', to: 'User8', flow: 2.67 }, { from: 'User1', to: 'User9', flow: 1.1 }, { from: 'User1', to: 'User10', flow: 8 }, { from: 'User1', to: 'User11', flow: 18.33 }, { from: 'User1', to: 'User3', flow: 52.33 }, { from: 'User1', to: 'User12', flow: 5.33 }, { from: 'User1', to: 'User13', flow: 16 }, { from: 'User1', to: 'User14', flow: 18.33 }, { from: 'User1', to: 'User7', flow: 16.67 }, { from: 'User1', to: 'User14', flow: 0.67 }, { from: 'User1', to: 'User4', flow: 0.43 }, { from: 'User1', to: 'User8', flow: 1 }, { from: 'User1', to: 'User11', flow: 4 }, { from: 'User1', to: 'User10', flow: 2.47 }, { from: 'User1', to: 'User15', flow: 48.87 }, { from: 'User1', to: 'User7', flow: 9.13 }, { from: 'User1', to: 'User12', flow: 6 }, { from: 'User1', to: 'User10', flow: 3.13 }, { from: 'User1', to: 'User14', flow: 22.67 }, { from: 'User1', to: 'User7', flow: 2.53 }, { from: 'User1', to: 'User8', flow: 3.67 }, { from: 'User1', to: 'User4', flow: 41.43 }, { from: 'User1', to: 'User5', flow: 20.33 }, { from: 'User1', to: 'User6', flow: 5.03 }, { from: 'User1', to: 'User3', flow: 52.5 }, { from: 'User1', to: 'User16', flow: 1.7 }, { from: 'User1', to: 'User1', flow: 1.33 }, { from: 'User1', to: 'User1', flow: 4.33 }, { from: 'User1', to: 'User6', flow: 15.67 }, { from: 'User1', to: 'User14', flow: 6.17 }, { from: 'User1', to: 'User9', flow: 6 }, { from: 'User4', to: 'User17', flow: 17.33 }, { from: 'User5', to: 'User12', flow: 1.33 }, { from: 'User6', to: 'User10', flow: 2.13 }, { from: 'User7', to: 'User17', flow: 19.67 }, { from: 'User9', to: 'User4', flow: 3.33 } ];

    I'm getting error:

    chartjs-chart-sankey.esm.js:109 Uncaught RangeError: Maximum call stack size exceeded at nodeCount (chartjs-chart-sankey.esm.js:109:1) at chartjs-chart-sankey.esm.js:109:1 at Array.reduce (<anonymous>) at nodeCount (chartjs-chart-sankey.esm.js:109:1) at chartjs-chart-sankey.esm.js:109:1 at Array.reduce (<anonymous>) at nodeCount (chartjs-chart-sankey.esm.js:109:1) at chartjs-chart-sankey.esm.js:109:1 at Array.reduce (<anonymous>) at nodeCount (chartjs-chart-sankey.esm.js:109:1)

    when I reduce array in half everything works fine.

    bug 
    opened by kkatusic 6
  • Refresh problem when updating data

    Refresh problem when updating data

    Hi !

    I am implementing sankey diagrams on a project. I have a great result, thanks for this project!

    However, there is a refresh problem when I update the data, especially when I reduce the data of all the nodes.

    I made an example here : https://codesandbox.io/s/update-data-j3rvy?file=/src/index.js

    sankey_issue

    The size of the nodes is very small, while there is space to draw them higher.

    I found a way around the problem by making two calls to the update() function (which is not very nice).

    I tried to look in the code without finding the problem.

    Can you help me to find a fix?

    Thanks for your help.

    bug 
    opened by nassissme 5
  • FIX order of draw calls in SankeyController

    FIX order of draw calls in SankeyController

    Canvas paints new draw operations on top of existing ones. Due to the fact that the _drawLabels method is invoked first, the text must compete with the transparent Flows drawn over it which limits the range of colors that are legible/visible (as well as fidelity of the text) within the chart. I changed the order of the calls such that _drawLabels occurs after the for expression for drawing the Flows.

    enhancement 
    opened by celgra 5
  • Cannot read property 'prototype' of undefined

    Cannot read property 'prototype' of undefined

    When I try to register the SankeyController, I get "Cannot read property 'prototype' of undefined". Here is a code snippet:

    import type { ChartDataset, ChartOptions } from 'chart.js';
    import { Chart } from 'chart.js';
    import { SankeyController, Flow } from 'chartjs-chart-sankey';
    
    Chart.register(SankeyController, Flow);
    

    Would appreciate some help! Thanks!

    opened by ritvik-statsig 4
  • Values and Units of Measurement

    Values and Units of Measurement

    Added showValues and unitOfMeasure options: datasets: [ { data: [{ from: 'TEST1', to: 'TEST2', flow: 15}, {from: 'TEST3', to: 'TEST2', flow: 20}, {from: 'TEST4', to: 'TEST2', flow: 25}, {from: 'TEST2', to: 'TEST6', flow: 60}, {from: 'TEST5', to: 'TEST6', flow: 10}], showValues: true, unitOfMeasure: "kW", colorFrom: (c) => getColor(c.dataset.data[c.dataIndex].from), colorTo: (c) => getColor(c.dataset.data[c.dataIndex].to), borderWidth: 0, borderColor: 'black', } ],

    values_unitsOfMeasurement

    opened by OverSamu 4
  • Add size option, update readme

    Add size option, update readme

    Hello there.

    I propose two things:

    1. An additional boolean configuration parameter 'adjustOverlaps'. The reason for that is that I have more 'out-connections' than 'in-connections'. (basically elements may fall into multiple categories) image It doesn't look nice. So the 'adjustOverlaps === true' param does the following: image

    By default it is set to 'false'. The usual logic stays the same.

    1. An updated way to calculate the largest node. This is a controversian one. But it helped me. The problem was due to the described above thing - more 'out-connections' than 'in-connections'. The 'findLargestNode' returned a node from a middle which then led to a visual bug. It got: image But i expected one of the images above.

    I added the 'tree.html' file which can reproduce the issue if the 'findLargestNode' function is reverted back. Also there is a test for that. expect(oneThenTwo).toEqual(jasmine.objectContaining({y: 28})); It failed here because 'y' was undefined;

    The controvercial thing is that a few tests are broken because charts do not conform to the png images provided. I'd be nice you if could help with those images.

    Thanks

    enhancement 
    opened by artemkosenko 4
  • cannot handle circular flows

    cannot handle circular flows

    Hi! I'm a commiter in https://github.com/Gnucash/gnucash/ and keen to import this nice module for cash flow charts. I hope you wouldn't mind? It'd need to wait for chartJS-3 release first. One issue: it doesn't seem to sanity check for circular flows?

    { from:"A", to:"B", flow:10 },
    { from:"B", to:"C", flow:10 },
    { from:"C", to:"A", flow:10 }
    
    bug 
    opened by christopherlam 4
  • Priorities issue

    Priorities issue

    Hi

    Data: [{ from: 'TEST1', to: 'TEST2', flow: 15}, {from: 'TEST3', to: 'TEST2', flow: 20}, {from: 'TEST4', to: 'TEST2', flow: 25}, {from: 'TEST4', to: 'TEST5', flow: 25}, {from: 'TEST2', to: 'TEST6', flow: 60}, {from: 'TEST5', to: 'TEST6', flow: 25}, {from: 'TEST7', to: 'TEST6', flow: 25}]

    Priorities: { TEST1: 1, TEST2: 1, TEST3: 2, TEST4: 3, TEST5: 2, TEST6: 1, TEST7: 4 }

    test1

    Priorities: { TEST1: 2, TEST2: 1, TEST3: 3, TEST4: 4, TEST5: 2, TEST6: 1, TEST7: 1 }

    test2

    Why does this happen? The TEST2 node should leave free space for the connection between the TEST7 and TEST6 nodes.

    Thanks in advance

    bug 
    opened by OverSamu 3
  • Changing font color

    Changing font color

    Hello, is it possible to change the default font color? I have tried various ways, for example setting Chart.defaults.color = '#fffff'; and changing the color in the dataset option (but this only changes the label at the top.

    Thank you for developing this plugin.

    enhancement 
    opened by Frohrer 3
  • Removing x-axis offsets hides right-most nodes

    Removing x-axis offsets hides right-most nodes

    I was wondering if there is any way of avoiding the X scale offset without having the right most nodes disappearing. If I do not set the scales.x.offset property tu false this is what I see: image

    However, when I set the property to false, the offset is removed but the right most nodes too: image

    Thanks for the chart, it is really impressive.

    bug 
    opened by rubenlopezlozoya 3
  • Configurable columns length

    Configurable columns length

    The current column config behaviour is a bit confusing. With the config below my expectation was that it will define 4 columns prior to the 5th "Energy".

    datasets: [
      {
        data: [
          { from: "Oil", to: "Energy", flow: 15 },
          { from: "Natural Gas", to: "Energy", flow: 20 },
          { from: "Coal", to: "Energy", flow: 25 },
          { from: "Electricity", to: "Energy", flow: 25 },
        ],
        column: {
          "Oil": 0,
          "Natural Gas": 1,
          "Coal": 2,
          "Electricity": 3,
        },
      },
    ]
    

    After some investigation, it turns out that the count of columns is computed automatically based on the data and the actual visualization is broken.

    Screen Shot 2022-11-17 at 4 25 11 PM

    https://codesandbox.io/s/vue-js-2-chart-js-3-sankey-diagram-forked-b5ob9i?file=/src/App.vue:710-1316

    bug 
    opened by Mihailoff 1
  • Column Override breaks Flow graph

    Column Override breaks Flow graph

    Adding column Overrides can potentially break a graph.

    An example:

    column: {
              Oil: 0,
              Oil1: 1,
              Air1: 1,
              Air2: 2,
              Stuff1: 1,
              Stuff2: 2
            },
    

    With the following Dataset

    data: [
              { from: "Oil", to: "Air1", flow: 15 },
              { from: "Oil", to: "Stuff1", flow: 20 },
              { from: "Oil1", to: "Air2", flow: 25 },
              { from: "Oil1", to: "Stuff2", flow: 25 `},]`
    

    completly breaks the graph, as shown here:

    Screenshot_20221105_212016

    How I would expect it to look (without the crossed out flow):

    Screenshot 2022-11-05 212304

    { from: "Oil", to: "Oil1", flow: 15 }, was added for screenshot above

    A modified codepen example: https://codepen.io/mh2207/pen/WNyGxPX

    And Thanks for your hard work!

    bug 
    opened by MauriceHartmann 0
  • TypeError: nodes[0] is undefined - custom priority parameter

    TypeError: nodes[0] is undefined - custom priority parameter

    I'm using a custom priority parameter and getting the following error TypeError: nodes[0] is undefined

    https://github.com/kurkle/chartjs-chart-sankey/blob/9dbd19faa27a67000403197ca6940a2c2931e357/src/layout.js#L215

    nodes[0] assumes that there is always at least one element and this is not true in my case.

    [email protected] [email protected]

    bug 
    opened by Mihailoff 2
  • TypeError when this component is included in a vitest test suite

    TypeError when this component is included in a vitest test suite

    We have a setup where this component is used inside a Vue 3 app, which is tested with jest (works fine!).

    We are now moving to the latest vue tooling, and after porting the tests from jest to vitest, we get this error:

     ❯ TypedRegistry.isForType node_modules/chart.js/dist/chart.js:6136:74
    
     FAIL  tests/unit/caseDetail.spec.js [ tests/unit/caseDetail.spec.js ]
    TypeError: Cannot read properties of undefined (reading 'prototype')
        6134|     console.log(`this.type = ${this.type}`)
        6135|     console.log(`type = ${JSON.stringify(type)}`)
        6136|     return Object.prototype.isPrototypeOf.call(this.type.prototype, type.prototype);
           |                                                                          ^
        6137|   }
        6138|   register(item) {
     ❯ Registry._getRegistryForType node_modules/chart.js/dist/chart.js:6279:15
     ❯ node_modules/chart.js/dist/chart.js:6259:41
     ❯ Registry._each node_modules/chart.js/dist/chart.js:6258:15
     ❯ Registry.add node_modules/chart.js/dist/chart.js:6216:10
     ❯ Function.value [as register] node_modules/chart.js/dist/chart.js:7549:16
     ❯ src/components/SankeyChart.vue:11:29
     ❯ async /app/frontend/src/components/CaseDetailPage.vue:14:31
     ❯ async /app/frontend/tests/unit/caseDetail.spec.js:14:31
    

    it occurs in src/components/SankeyChart.vue on this line:

    Chart.register(LinearScale, SankeyController, Flow)
    

    I have set up a super-simple example to reproduce (https://gitlab.com/simevo/vue-3-vitest-basic-example), starting from the basic vue test example, I added chart.js and Chart.register(LinearScale) (works fine)

    As soon as I import import { SankeyController, Flow } from 'chartjs-chart-sankey' and change Chart.register(LinearScale) to Chart.register(LinearScale, SankeyController, Flow) the error pops up.

    Sorry for the convoluted use case, I just hope this helps you find some hidden bug in your nice module!

    opened by simevo 2
  • Pan / Scroll Sankey Chart?

    Pan / Scroll Sankey Chart?

    Hello

    Firstly, thanks for this plugin. I've been able to quickly get some awesome charts going. Much obliged.

    For most of my data, I have charts that have a few sources (say 10 or less) and hundreds of outputs. I'd like to vertically scroll the Sankey chart, if possible. Considering the number out connections I have, having a very large vertical canvas results in noticeable lag / overhead.

    (ie, simply making the canvas large isn't a great solution as im drawing 4k pixels vertically... )

    Id like to limit the drawing and provide some mechanism to vertically scroll / pan. Im aware Chart.js has this feature, but unless I am mistaken I can't seem to find the right way of getting It to work with this plugin.

    For example, here's a zoomed out chart to provide a visual example ( had to split it over 2 images)

    Screen Shot 2022-09-21 at 10 25 13 AM Screen Shot 2022-09-21 at 10 25 50 AM

    Is there a simple example of a working scrolling solution for Sankey charts?

    Secondly, is there a way to pin some elements to a fixed / relative to the viewport on screen position? I'd love my left side elements to remain at the top even when scrolling, so one has a consistent reference point.

    Thank you again!

    enhancement 
    opened by vade 1
  • flickering issue on resize

    flickering issue on resize

    @kurkle From the documentation example, is there any optimization we can do to avoid the flickering issue?

    Charts built from the original chart.js usually would't have this issue.

    https://user-images.githubusercontent.com/35160613/183940648-f362d3ee-d197-41ef-8305-292c97dbcdfb.mov

    bug 
    opened by aboveyunhai 1
Releases(v0.12.0)
Owner
Jukka Kurkela
Programmer of various languages and architectures since 1980's
Jukka Kurkela
Chart.js Venn and Euler Diagrams

Chart.js Venn and Euler Diagram Chart Chart.js module for charting venn diagrams with up to five sets. Adding new chart type: venn and euler. Related

UpSet.js 23 Dec 6, 2022
Chart.js module for creating treemap charts

chartjs-chart-treemap Chart.js v3.6.0 module for creating treemap charts. Implementation for Chart.js v2 is in 2.x branch Documentation You can find d

Jukka Kurkela 99 Dec 18, 2022
A Simple Dashboard Chart in Laravel Nova using Chart JS

A Simple Dashboard Chart in Laravel Nova using Chart JS. Starting create your own dashboard with Chart JS Integration can save your time and help you maintain consistency across standard elements such as Bar, Stacked, Line, Area, Doughnut and Pie Chart.

Kuncoro Wicaksono 177 Jan 4, 2023
Chart.js plugin to defer initial chart updates

Chart.js plugin to defer initial chart updates until the user scrolls and the canvas appears inside the viewport, and thus trigger the initial chart a

Chart.js 97 Nov 9, 2022
Bar Funnel Chart extension for Chart.js

Chart.BarFunnel.js Provides a Bar Funnel Chart for use with Chart.js Documentation To create a Bar Funnel Chart, include Chart.BarFunnel.js after Char

Chart.js 58 Nov 24, 2022
TradeX-chart is a trade chart written in plain (vanilla) JavaScript with minimal dependencies

TradeX-chart is a trade chart written in plain (vanilla) JavaScript with minimal dependencies; use it with any framework or backend.

null 24 Dec 12, 2022
Chart.js module for charting financial securities

Chart.js Financial Charting Chart.js module for Candlestick and OHLC charts Roadmap Chart.js 2.7.0 added our timeseries scale as new option called dis

Chart.js 630 Dec 29, 2022
Redefined chart library built with React and D3

Recharts Introduction Recharts is a Redefined chart library built with React and D3. The main purpose of this library is to help you to write charts i

recharts 19.4k Jan 2, 2023
:bar_chart: A D3-based reusable chart library

c3 c3 is a D3-based reusable chart library that enables deeper integration of charts into web applications. Follow the link for more information: http

C3.js 9.2k Jan 2, 2023
GPL version of Javascript Gantt Chart

dhtmlxGantt Getting started | Features | Follow us | License | Useful links dhtmlxGantt is an open source JavaScript Gantt chart that helps you illust

null 952 Dec 29, 2022
🍞📊 Beautiful chart for data visualization.

?? ?? Spread your data on TOAST UI Chart. TOAST UI Chart is Beautiful Statistical Data Visualization library. ?? Packages The functionality of TOAST U

NHN 5.2k Jan 2, 2023
:bar_chart: Re-usable, easy interface JavaScript chart library based on D3.js

billboard.js is a re-usable, easy interface JavaScript chart library, based on D3 v4+. The name "billboard" comes from the famous billboard chart whic

NAVER 5.4k Jan 1, 2023
:bar_chart: A library of modular chart components built on D3

Plottable Plottable is a library of chart components for creating flexible, custom charts for websites. It is built on top of D3.js and provides highe

Palantir Technologies 2.9k Dec 31, 2022
Chart image and QR code web API

QuickChart QuickChart is a service that generates images of charts from a URL. Because these charts are simple images, they are very easy to embed in

Ian Webster 1.3k Dec 25, 2022
📈 A small, fast chart for time series, lines, areas, ohlc & bars

?? μPlot A small (~35 KB min), fast chart for time series, lines, areas, ohlc & bars (MIT Licensed) Introduction μPlot is a fast, memory-efficient Can

Leon Sorokin 7.5k Jan 7, 2023
TChart.js - simple and configurable Bar and Line Chart library in Javascript

TChart.js Simple and configurable Bar and Line Chart library in Javascript Description TChart.js is a canvas-based simple Javascript Bar and Line Char

null 4 Mar 3, 2021
🍞📊 Beautiful chart for data visualization.

?? ?? Spread your data on TOAST UI Chart. TOAST UI Chart is Beautiful Statistical Data Visualization library. ?? Packages The functionality of TOAST U

NHN 5.2k Jan 6, 2023
The power of Chart.js in Jupyter !

The power of Chart.js in Jupyter Notebooks Installation You can install ipychart from your terminal using pip or conda: # using pip $ pip install ipyc

Nicolas H 68 Dec 8, 2022
Chart.js bindings for OCaml

chartjs-ocaml: OCaml bindings for Chart.js This library provides OCaml bindings for the Chart.js charting library and some popular plugins. Following

Alex Yanin 13 Aug 20, 2022