Skip to content

Comparison table

Jae Sung Park edited this page Mar 4, 2024 · 10 revisions

2024 Version

  billboard.js Chart.js Apache Echarts Recharts plotly.js Frappe Charts
Supported Types(1) 18 9 27 9 40 7
Methods & Options(1) 255+ 108+ 55+ 46+ 30+ 78+
Release Frequency(2) Minor: 4
Patch: 15
Minor: 3
Patch: 6
Minor: 2 Major: 1
Minor: 10
Patch: 20
Minor: 10
Patch: 14
0

The above data is taken on 21st Feb, 2024.
(1) Some libraries API doc aren't clear to get exact number and it can be an estimation counted manually.
(2) Frequency in a year of 2023.

Alternative Refs.

2017 Version

  billboard.js ChartJS Highcharts C3.js nvd3 chartist echarts plotly.js Britecharts TauCharts
Graphic Type Vector Bitmap Vector Vector Vector Vector Bitmap Vector Vector Vector
Supported Types 11 9 38 11 8 8 18 13 8 5
Dependency D3 v4+ chartjs-color, moment - D3 v3 D3 v3 - zrender 50 modules D3 v4+ D3 v3
Last Version 1.1.1 2.7.1 6.0.2 0.4.18 1.8.6 0.11.0 3.7.2 1.31.2 2.4.0 1.2.2
Size(minified) 169KB 154KB 187KB 183KB 248KB 39.3KB 651KB 2.23MB 1.96MB 457KB
Touch(Mobile) Support O O O X O X O X X
API Doc Good(1) Confuse Good Good Poor Good Good/Confuse Poor Good Good/Confuse
Interface(2) (Learning Curve) Simple Simple Simple Simple Diffucult Diffucult Simple Difficult Intermediate Intermediate
Since 2017.06 2013.05 2010.08 2014.01 2013.05 2014.04 2013.06 2015.11 2015.09 2015.01
npm Downloads(3) (2017.06 ~ 10) 4,541 2,485,670 1,747,871 420,067 370,913 279,570 252,978 158,361 12,013 24,338
GitHub Star(3) 1,788 33,165 6,826 7,246 6,221 10,082 21,457 7,021 2,850 1,533
Quality/Activity(3) (npms.io) 72 80 63 23 65 57 66 67 73 67
3rd party(3) 8 276 151 73 34 46 139 15 2 2
License MIT MIT Commercial/
Free(for opensource or personal use)
MIT Apache 2.0 MIT BSD 3 Clause MIT Apache 2.0 Apache 2.0

(1) I'm switching over my charts from nvd3 to billboard.js since the documentation of the API's is much more thorough.
(3) Indicators are measured at Nov. 1st, 2017.

Interface comparisons(2)

Click the library name to expand

billboard.js / C3.js
var chart = bb.generate({
  bindto: '#chart',
  data: {
    columns: [
      ['data1', 30, 20, 50, 40, 60, 50],
      ['data2', 200, 130, 90, 240, 130, 220],
      ['data3', 300, 200, 160, 400, 250, 250],
      ['data4', 200, 130, 90, 240, 130, 220],
      ['data5', 130, 120, 150, 140, 160, 150],
      ['data6', 90, 70, 20, 50, 60, 120],
    ],
    type: 'bar',
    types: {
      data3: 'spline',
      data4: 'line',
      data6: 'area',
    },
    groups: [
      ['data1','data2']
    ]
  },
  bar: {
    width: {
      ratio: 0.5 // this makes bar width 50% of length between ticks
    }
  },
  title: {
    text: 'Basic Example'
  },
  zoom: {
    enabled: true
  }
});
Chart.js
var mixedChart = new Chart(document.getElementById("myChart"), {
  type: 'bar',
  data: {
    datasets: [{
          label: 'Bar Dataset',
          data: [10, 20, 30, 40],
           backgroundColor: 'rgba(255, 99, 132, 0.2)',
        }, {
          label: 'Line Dataset',
          data: [0, 15, 30, 50],
          borderColor: 'rgba(255, 255, 0, 0.1)',
	 	  backgroundColor: 'rgba(255, 99, 132, 0.1)',
          // Changes this dataset to become a line
          type: 'line'
        }],
    labels: ['January', 'February', 'March', 'April']
  },
  options: {
        scales: {
            yAxes: [{
                ticks: {
                    beginAtZero:true
                }
            }]
        },
      title: {
            display: true,
            text: 'Chart.js example'
        },
      legend: {
            display: true,
            position: 'bottom'
        }
    }
});
Highcharts
Highcharts.chart('container', {
    chart: {
        zoomType: 'xy'
    },
    title: {
        text: 'Average Monthly Temperature and Rainfall in Tokyo'
    },
    subtitle: {
        text: 'Source: WorldClimate.com'
    },
    xAxis: [{
        categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
            'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
        crosshair: true
    }],
    yAxis: [{ // Primary yAxis
        labels: {
            format: '{value}°C',
            style: {
                color: Highcharts.getOptions().colors[1]
            }
        },
        title: {
            text: 'Temperature',
            style: {
                color: Highcharts.getOptions().colors[1]
            }
        }
    }, { // Secondary yAxis
        title: {
            text: 'Rainfall',
            style: {
                color: Highcharts.getOptions().colors[0]
            }
        },
        labels: {
            format: '{value} mm',
            style: {
                color: Highcharts.getOptions().colors[0]
            }
        },
        opposite: true
    }],
    tooltip: {
        shared: true
    },
    legend: {
        layout: 'vertical',
        align: 'left',
        x: 120,
        verticalAlign: 'top',
        y: 100,
        floating: true,
        backgroundColor: (Highcharts.theme && Highcharts.theme.legendBackgroundColor) || '#FFFFFF'
    },
    series: [{
        name: 'Rainfall',
        type: 'column',
        yAxis: 1,
        data: [49.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4],
        tooltip: {
            valueSuffix: ' mm'
        }

    }, {
        name: 'Temperature',
        type: 'spline',
        data: [7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2, 26.5, 23.3, 18.3, 13.9, 9.6],
        tooltip: {
            valueSuffix: '°C'
        }
    }]
});
nvd3
nv.addGraph(function() {
  var data = [{
      "key": "Quantity",
      "bar": true,
      "color": "#ccf",
      "values": [
        [1136005200000, 1271000.0],
        [1138683600000, 1271000.0],
        [1141102800000, 1271000.0],
        [1143781200000, 0],
        [1146369600000, 0],
      ]
    },

    {
      "key": "Price",
      "color": "#333",
      "values": [
        [1136005200000, 71.89],
        [1138683600000, 75.51],
        [1141102800000, 68.49],
        [1143781200000, 62.72],
        [1146369600000, 70.39]
      ]
    }
  ];

  var chart = nv.models.linePlusBarChart()
    .margin({
      top: 30,
      right: 60,
      bottom: 50,
      left: 70
    })
    //We can set x data accessor to use index. Reason? So the bars all appear evenly spaced.
    .x(function(d, i) {
      return i
    })
    .y(function(d, i) {
      return d[1]
    });

  chart.xAxis.tickFormat(function(d) {
    var dx = data[0].values[d] && data[0].values[d][0] || 0;
    return d3.time.format('%x')(new Date(dx))
  });

  chart.y1Axis.tickFormat(d3.format(',f'));
  chart.y2Axis.tickFormat(function(d) {
      return '$' + d3.format(',f')(d)
    });

  chart.bars.forceY([0]);

  d3.select('#chart svg')
    .datum(data)
    .transition()
    .duration(0)
    .call(chart);

  nv.utils.windowResize(chart.update);

  return chart;
});
chartist
new Chartist.Line('.ct-chart', {
  labels: [1, 2, 3, 4, 5, 6, 7, 8],
  series: [
    [11, 12, 13, 11, 12, 10, 11, 10],
    [12, 11, 17, -1, 0, 18, -2, 8],
    [0, 8, 12, 1, 15, 3, 18, 1],
    [3, 2, 12, 15, 16, 3, 18, -3]
  ]
}, {
  high: 20,
  low: -3,
  fullWidth: true,
  // As this is axis specific we need to tell Chartist to use whole numbers only on the concerned axis
  axisY: {
    onlyInteger: true,
    offset: 20
  }
});
echarts
var myChart = echarts.init(document.getElementById("container"));
myChart.setOption({
    title: {
        text: 'title text'
    },
    tooltip: {
        trigger: 'axis',
        formatter: function (params) {
            params = params[0];
            var date = new Date(params.name);
            return date.getDate() + '/' + (date.getMonth() + 1) + '/' + date.getFullYear() + ' : ' + params.value[1];
        },
        axisPointer: {
            animation: false
        }
    },
    xAxis: {
        type: 'time',
        splitLine: {
            show: false
        }
    },
    yAxis: {
        type: 'value',
        boundaryGap: [0, '100%'],
        splitLine: {
            show: false
        }
    },
    series: [{
        name: 'data',
        type: 'line',
        showSymbol: false,
        hoverAnimation: false,
        data: [
            {
	            name: data1,
		        value: ["2017/11/20",200]
	        },
            {
	            name: data2,
		        value: ["2017/11/21",120]
	        }
        ]
    }]
}, true);
plotly.js
(function() {
	var d3 = Plotly.d3;

	var WIDTH_IN_PERCENT_OF_PARENT = 100,
		HEIGHT_IN_PERCENT_OF_PARENT = 80;

	var gd3 = d3.select('body')
		.append('div')
		.style({
			width: WIDTH_IN_PERCENT_OF_PARENT + '%',
			'margin-left': (100 - WIDTH_IN_PERCENT_OF_PARENT) / 2 + '%',

			height: HEIGHT_IN_PERCENT_OF_PARENT + 'vh',
			'margin-top': (100 - HEIGHT_IN_PERCENT_OF_PARENT) / 2 + 'vh'
		});

	var gd = gd3.node();
	var trace1 = {
	  x: [0, 1, 2, 3, 4, 5], 
	  y: [1.5, 1, 1.3, 0.7, 0.8, 0.9], 
	  type: 'scatter'
	};

	var trace2 = {
	  x: [0, 1, 2, 3, 4, 5], 
	  y: [1, 0.5, 0.7, -1.2, 0.3, 0.4], 
	  type: 'bar'
	};

	var layout = {
		title: 'Plotly.js Basic Example',
		font: {
			size: 16
	  }
	}

	var data = [trace1, trace2];
	Plotly.plot(gd, data, layout);

	window.onresize = function() {
		Plotly.Plots.resize(gd);
	};
})();
Britecharts
var lineChart = new line();
var container = d3.select('.js-container');
 
 lineChart
    .isAnimated(true)
    .aspectRatio(0.5)
    .grid('horizontal')
    .tooltipThreshold(600)
    .width(600)
    .dateLabel('fullDate')
    .on('customMouseOver', chartTooltip.show)
    .on('customMouseMove', chartTooltip.update)
    .on('customMouseOut', chartTooltip.hide);

container.datum({
    dataByTopic: [
        {
            topicName: 'San Francisco',
            topic: 123,
            dates: [
                {
                    date: '2017-01-16T16:00:00-08:00',
                    value: 1
                },
                {
                    date: '2017-01-16T17:00:00-08:00',
                    value: 2
                }
            ]
        },
        {
            topicName: 'Other',
            topic: 345,
            dates: [
                {...},
                {...}
            ]
        }
    ]
}).call(lineChart);
TauCharts
var chart = new tauCharts.Chart({
	data: [
		{ name: "John", age: 30, gender: 'Male',   hasChild: true  },
	        { name: "Jim", age: 28, gender: 'Male',   hasChild: false  },
        	{ name: "Tom", age: 27, gender: 'Male',   hasChild: true  },
	        { name: "Edd", age: 29, gender: 'Male',   hasChild: true  },
	        { name: "Jack", age: 23, gender: 'Male',   hasChild: false  },
	        { name: "Mary", age: 22, gender: 'Female', hasChild: false },
	        { name: "Anna", age: 25, gender: 'Female', hasChild: true },
	        { name: "Lisa", age: 26, gender: 'Female', hasChild: true },
	        { name: "Donna", age: 27, gender: 'Female', hasChild: true },
	        { name: "Jane", age: 28, gender: 'Female', hasChild: true }
	],
	type:'line',
	x:'Year',
	y:'Points',
	color:'Position',
	size:null,
	plugins: [
		tauCharts.api.plugins.get('tooltip')(),
		tauCharts.api.plugins.get('legend')(),
		tauCharts.api.plugins.get('quick-filter')(),
		tauCharts.api.plugins.get('trendline')(),
	]
});

chart.renderTo('#container');