-
Notifications
You must be signed in to change notification settings - Fork 354
Comparison table
Jae Sung Park edited this page Aug 13, 2024
·
12 revisions
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 |
Note
The above data are 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.
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 |
Note
(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.
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');
- Why we decided to start billboard.js?
- Comparison table
- How to migrate from C3.js?
- Who's using billboard.js
- Third party applications
- Themes
- Roadmap
- Architecture & Event
- Plugin Interface
- Release workflow
- How behaves for dynamic loading?
- How tooltip behaves on grouped option?
- How to load as ESM directly from the browser?
- How to implement realtime chart?
- How to bundle for legacy browsers?
- How to generate chart image in Node.js environment?
- Understanding padding