To explain my problem, I use the following code on the c3js website (http://c3js.org/samples/chart_bar.html) :
var chart = c3.generate({
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
['data2', 130, 100, 140, 200, 150, 50]
],
type: 'bar'
},
bar: {
width: {
ratio: 0.5 // this makes bar width 50% of length between ticks
}
// or
//width: 100 // this makes bar width 100px
}
});
setTimeout(function () {
chart.load({
unload : true,
columns: [
['data3', 130, -150, 200, 300, -200, 100]
]
});
}, 3000);
setTimeout(function () {
chart.load({
unload : true,
columns: [
['data1', 30, 200, 100, 400, 150, 250],
['data2', 130, 100, 140, 200, 150, 50]
],
});
}, 4000);
I click on data1 to hide one of the data before it is updated, I have the following, which is normal:
But after the final update, I got a weird behavior where data1 is "half displayed":
Is there any way to solve this issue?
Thank you
The issue seems to be the drawing logic of c3. But there is a workaround for this issue. Check the following code:
setTimeout(function () {
chart.load({
unload : true,
columns: [
['data1', 30, 200, 100, 400, 150, 250],
['data2', 130, 100, 140, 200, 150, 50]
],
done : function() {
// After chart is drawn, shown all the hidden legend.
chart.show();
}
});
}, 4000);
Related
Normally in C3.js to create multiple Y axes you would doe something like this:
var chart = c3.generate({
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
['data2', 50, 20, 10, 40, 15, 25]
],
axes: {
data1: 'y',
data2: 'y2'
}
},
axis: {
y2: {
show: true
}
}
});
However my data is different/dynamic something like this:
['week', 1, 2, 3, 4, 5, 6],
['feed cow 30', 30, 200, 100, 400, 150, 250],
['weight cow 30', 30, 200, 100, 400, 150, 250],
['week', 1, 2, 3, 4, 5, 6],
['feed cow 40', 30, 200, 100, 400, 150, 250],
['weight cow 40', 30, 200, 100, 400, 150, 250],
['week', 1, 2, 3, 4, 5, 6],
['feed cow 60', 30, 200, 100, 400, 150, 250],
['weight cow 60', 30, 200, 100, 400, 150, 250],
So my Column names are dynamic. I create an array for the plotting of the data X axes. So my data is like this:
data: {
xs: xs,
columns: graphdata,
type: "line", .......
Now I want to have 2 Y axes, one for weight and one for feed. How can I achieve that?
Got it:
var axisData = {}; axisData[graphdata[2][0]] = "y"; axisData[graphdata[1][0]] = "y2";
....
data: {
xs: xs,
columns: graphdata,
axes : axisData,
type: "line",
},
Having this code snippet in Billboard.js:
var chart = bb.generate({
data: {
columns: [
["data1", 30, 200, 100, 400, 150, 250],
["data2", 130, 100, 140, 200, 150, 50]
],
type: "spline"
},
bindto: "#SplineChart"
});
it will generate this chart:
As it can be seen, the Y axis has in this case the minimum value of 0 and the maximum of 400(or somewhere there).
Is there a way to get that value and store it into a variable?
If I understand correctly you want to get the domain for the Y axis. You can achieve it with:
chart.internal.y.domain()
Check the demo below:
var chart = bb.generate({
data: {
columns: [
["data1", 30, 200, 100, 400, 150, 250],
["data2", 130, 100, 140, 200, 150, 50]
],
type: "spline"
},
bindto: "#SplineChart"
});
var yDomain = chart.internal.y.domain()
console.log('y domain==> ', yDomain);
<script src="https://d3js.org/d3.v4.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/billboard.js/dist/billboard.min.css" rel="stylesheet"/>
<script src="https://cdn.jsdelivr.net/npm/billboard.js/dist/billboard.min.js"></script>
<div id="SplineChart"></div>
I've been using c3.js for some time now, but recently I stumbled across a problem. I'm using the Multiple XY Line Chart feature and my data set is huge. Is there a way to do the data-axis binding (the xs part) automatically instead of hard coding it?
var chart = c3.generate({
data: {
xs: {
'data1': 'x1',
'data2': 'x2',
.
.
.
'datan': 'xn',
},
columns: [
['x1', 10, 30, 45, 50, 70, 100],
['x2', 30, 50, 75, 100, 120],
.
.
.
['xn', 45, 60, 80, 120, 130],
['data1', 30, 200, 100, 400, 150, 250],
['data2', 20, 180, 240, 100, 190],
.
.
.
['datan', 10, 150, 220, 160, 300]
]
}
});
You just need to build a function that matches the syntax of your data series titles to the relevant x series
Assuming all the x1 / data1 etc stuff is in an object (allmydata) before you generate the chart you could do:
var allmydata = [
['x1', 10, 30, 45, 50, 70, 100],
['x2', 30, 50, 75, 100, 120],
['xn', 45, 60, 80, 120, 130],
['data1', 30, 200, 100, 400, 150, 250],
['data2', 20, 180, 240, 100, 190],
['datan', 10, 150, 220, 160, 300]
];
var match = function (dataStr) {
return dataStr.startsWith("data") ? dataStr.replace ("data", "x") : undefined;
};
var xs = {};
allmydata.forEach (function (series) {
var seriesName = series[0];
var xsName = match (seriesName);
if (xsName) {
xs[seriesName] = xsName;
}
});
var chart = c3.generate({
data: {
xs: xs,
columns: allmydata
}
});
http://jsfiddle.net/0f38ffsy/1/
I have set up an xy graph and I'm trying to load in a new dataset but for some reason the data never generates inside the graph:
<div id="graph"></div>
<script>
var chart = c3.generate({
bindto: '#graph',
data: {
xs: {
'data1': 'x1',
'data2': 'x2',
},
columns: [
['x1', 10, 30, 45, 50, 70, 100],
['x2', 30, 50, 75, 100, 120],
['data1', 30, 200, 100, 400, 150, 250],
['data2', 20, 180, 240, 100, 190]
]
}
});
setTimeout(function () {
chart.load({
bindto: '#graph',
data: {
xs: {
'data3': 'x3',
},
columns: [
['x3', 20, 40, 55, 60, 80, 110],
['data3', 30, 150, 260, 120, 90]
]
}
});
}, 2000);
</script>
Anyone have any idea why this might be? I know that chart.unload works fine and I've tried playing with adding and removing the bindto: 'graph', but nothing has worked
According to the docs, the load function does not need the data parameter, so it should look like this:
chart.load({
bindto: '#graph',
xs: {
'data3': 'x3',
},
columns: [
['x3', 20, 40, 55, 60, 80, 110],
['data3', 30, 150, 260, 120, 90]
]
});
Demo snippet:
var chart = c3.generate({
bindto: '#graph',
data: {
xs: {
'data1': 'x1',
'data2': 'x2',
},
columns: [
['x1', 10, 30, 45, 50, 70, 100],
['x2', 30, 50, 75, 100, 120],
['data1', 30, 200, 100, 400, 150, 250],
['data2', 20, 180, 240, 100, 190]
]
}
});
setTimeout(function () {
chart.load({
bindto: '#graph',
xs: {
'data3': 'x3',
},
columns: [
['x3', 20, 40, 55, 60, 80, 110],
['data3', 30, 150, 260, 120, 90]
]
});
}, 2000);
<link href="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.8/c3.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.8/c3.js"></script>
<div id="graph"></div>
DEMO HERE
In the demo I am attempting to unload all current datasets and load new ones like this:
Using C3.js
chart.unload();
chart.load({
columns: [
['data1', 130, 120, 150, 140, 160],
['data2', 30, 20, 50, 40, 60, 50],
],
});
This is obviously not the correct way to handle this process as the demo shows, this does not work correctly.
The C3 tutorial states that data sets should be replaced like this:
chart.load({
columns: [
['data1', 130, 120, 150, 140, 160],
['data2', 30, 20, 50, 40, 60, 50],
],
unload: ['data3', 'data4', 'data5'],
});
Again the demo shows this works correctly however...
QUESTION
How can I unload ALL current datasets and replace them with new ones without having to specify their individual data names (data3,data4) etc?
Note: The data sets are variable in name and quanity, hence why I just want to unload ALL.
Fundamentally all I want to do is replace the data sets with new ones on click.
I don't know if it could be usefull for you, in the past I have used this (unload in the same function of load). For your code it should be
chart.load({
columns: [
['data1', 130, 120, 150, 140, 160, 150],
['data4', 30, 20, 50, 40, 60, 50],
],
unload: chart.columns,
});
working fiddle
$('#A').on('click', function () {
chart.load({
columns: [
['data1', 130, 120, 150, 140, 160, 150],
['data4', 30, 20, 50, 40, 60, 50],
],
unload: chart.columns,
});
});
$('#B').on('click', function () {
chart.load({
columns: [
['data1', 130, 120, 150, 140, 160, 150],
['data4', 30, 20, 50, 40, 60, 50],
],
unload: chart.columns,
});
});