With C3.js, how can I maintain bar width ratio when zooming in? - c3.js

I have a c3.js bar graph with a subgraph and zooming enabled. I would like for the graph to show more x-tick labels and make the bars a little wider when the user selects a smaller area.
Here's what my graph looks like zoomed out (left) and zoomed in (right):
Here's a fiddle.
var chart = c3.generate({
bindto: '#chart',
data: {
x: 'x',
columns: [
['x', '2015-01-01', '2015-02-01', '2015-03-01', '2015-04-01', '2015-05-01', '2015-06-01', '2015-07-01', '2015-08-01', '2015-09-01', '2015-10-01', '2015-11-01', '2015-12-01', '2016-01-01', '2016-02-01', '2016-03-01', '2016-04-01', '2016-05-01', '2016-06-01', '2016-07-01', '2016-08-01'],
['y', 100, 200, 300, 200, 100, 450, 800, 900, 12, 70, 500, 450, 20, 100, 200, 300, 200, 100, 450, 800, 900, 12, 70, 500, 450, 20]
],
type: 'bar',
color: function(color, d) {
var color = d3.rgb("#E47911");
if (d.index % 2 == 0) {
color = color.darker(1.2);
}
return color;
}
},
bar: {
width: { ratio: 1.0 }
},
axis: {
x: {
type: 'timeseries',
tick: {
format: "%b",
fit: true
}
},
},
subchart: {
show: true
},
zoom: {
enabled: true
}
});
I'd like it to look more like this when zoomed in:
.
Is there a way to make this happen using C3?

copy the code to your fiddle js panel. type: 'categories' changes the bar scales.
var chart = c3.generate({
bindto: '#chart',
data: {
x: 'x',
columns: [
['x', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
['y', 100, 200, 300, 200, 100, 450, 800, 900, 12, 70, 500, 450, 20, 100, 200, 300, 200, 100, 450, 800, 900, 12, 70, 500, 450, 20]
],
type: 'bar',
color: function(color, d) {
var color = d3.rgb("#E47911");
if (d.index % 2 == 0) {
color = color.darker(1.2);
}
return color;
}
},
bar: {
width: { ratio: 0.8 }
},
axis: {
x: {
type: 'categories',
tick: {
format: "%b",
fit: true
}
},
},
subchart: {
show: true
},
zoom: {
enabled: true
}
});

Related

How to configure linear labels in Time Cartesian Chartjs?

I need to show labels on the x-axis every 2 hours (0h, 2h, 4h...). What am I missing?
<script>
var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'line',
data: {
//labels: ['0h', '2h', '4h', '6h', '8h', '10h', '12h', '14h', '16h', '18h', '20h', '22h', '0h'],
datasets: [{
label: 'AAA1111',
//xAxisID: 'Hora',
//yAxisID: 'Velocidade',
data: [{
t: new Date("2015-3-15 12:30"),
y: 12
},
{
t: new Date("2015-3-15 14:40"),
y: 45
},
{
t: new Date("2015-3-15 17:50"),
y: 77
}
],
borderColor: 'rgba(255, 0, 0, 1)',
borderWidth: 4,
fill: false,
lineTension: 0,
lineJoint: "round",
spanGaps: true
}]
},
options: {
scales: {
xAxes: [{
type: 'time',
distribution: 'linear',
time: {
unit: 'hour',
//stepSize: 24??
},
ticks: {
source: 'data'
}
}]
}
}
});
</script>
The chart plots Time x Velocity.
Two small changes will achieve the desired result:
set stepSize: 2 to 'show labels on X axis every 2 hours (0h, 2h, 4h...)'
remove ticks: { source: 'data' } as that:
generates ticks from data (including labels from data {t|x|y} objects)"
Here's a working example based on the posted code:
var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'line',
data: {
//labels: ['0h', '2h', '4h', '6h', '8h', '10h', '12h', '14h', '16h', '18h', '20h', '22h', '0h'],
datasets: [{
label: 'AAA1111',
//xAxisID: 'Hora',
//yAxisID: 'Velocidade',
data: [{
t: new Date("2015-3-15 12:30"),
y: 12
},
{
t: new Date("2015-3-15 14:40"),
y: 45
},
{
t: new Date("2015-3-15 17:50"),
y: 77
}
],
borderColor: 'rgba(255, 0, 0, 1)',
borderWidth: 4,
fill: false,
lineTension: 0,
lineJoint: "round",
spanGaps: true
}]
},
options: {
scales: {
xAxes: [{
type: 'time',
distribution: 'linear',
time: {
unit: 'hour',
stepSize: 2
}
}]
}
}
});
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.9.3/dist/Chart.bundle.min.js"></script>
<canvas id="myChart"></canvas>

Datepicker and chartjs in Laravel (old chart data when hover)

I have an issue when displaying a chart. I have a function that load data by default for today. After that, I can select a date range. But there is an issue when hovering on labels. They load old chart values and lines. I know that I need to use destroy or update function. But I don't know how to implement it in my code.
Script:
<script type="text/javascript">
$(document).ready(function() {
getdata_chart();
{{-- chartjs --}}
function getdata_chart(start_date='', end_date='')
{
$.ajax({
url: "{{ route('ajaxdata.getdata_chart') }}",
method: "GET",
data:{
start_date:start_date, end_date:end_date
},
success: function(data) {
console.log(data);
var timeFormat = 'DD MMM YYYY г. kk:mm:ss ч.';
var progress = document.getElementById('animationProgress');
var dateANDtime = [];
var Gblok9osx = [];
var Gblok9osy = [];
var Gblok11osx = [];
var Gblok11osy = [];
var Gfilblok10 = [];
var Gfilblok11 = [];
var Gcvn = [];
var Gndk = [];
var Gndk2 = [];
for (var i in data) {
dateANDtime.push(data[i].timestamp);
Gblok9osx.push(data[i].blok9osx);
Gblok9osy.push(data[i].blok9osy);
Gblok11osx.push(data[i].blok11osx);
Gblok11osy.push(data[i].blok11osy);
Gfilblok10.push(data[i].filblok10);
Gfilblok11.push(data[i].filblok11);
Gcvn.push(data[i].cvn);
Gndk.push(data[i].ndk);
Gndk2.push(data[i].ndk2);
}
var chartdata = {
labels: dateANDtime,
datasets: [{
fill: false,
label: 'Отвес блок 9 x',
backgroundColor: 'rgba(199, 228, 238, 0.75)',
borderColor: 'rgba(1, 150, 200, 0.75)',
//hoverBackgroundColor: 'rgba(200, 200, 200, 0.75)',
hoverBorderColor: 'rgba(200, 200, 200, 1)',
data: Gblok9osx,
hidden: false
},
{
fill: false,
label: 'Отвес блок 9 y',
backgroundColor: 'rgba(163, 147, 222, 0.75)',
borderColor: 'rgba(50, 10, 200, 0.75)',
//hoverBackgroundColor: 'rgba(200, 200, 200, 1)',
hoverBorderColor: 'rgba(200, 200, 200, 1)',
data: Gblok9osy,
hidden: true
},
{
fill: false,
label: 'Отвес блок 11 x',
backgroundColor: 'rgba(221, 221, 241, 0.75)',
borderColor: 'rgba(100, 100, 200, 0.75)',
//hoverBackgroundColor: 'rgba(200, 200, 200, 1)',
hoverBorderColor: 'rgba(200, 200, 200, 1)',
data: Gblok11osx,
hidden: true
},
{
fill: false,
label: 'Отвес блок 11 y',
backgroundColor: 'rgba(147, 227, 227, 0.75)',
borderColor: 'rgba(1, 200, 200, 0.75)',
//hoverBackgroundColor: 'rgba(200, 200, 200, 1)',
hoverBorderColor: 'rgba(200, 200, 200, 1)',
data: Gblok11osy,
hidden: true
},
{
fill: false,
label: 'Филтрация блок 10',
backgroundColor: 'rgba(139, 105, 132, 0.75)',
borderColor: 'rgba(255, 1, 200, 0.75)',
//hoverBackgroundColor: 'rgba(200, 200, 200, 1)',
hoverBorderColor: 'rgba(200, 200, 200, 1)',
data: Gfilblok10,
hidden: true
},
{
fill: false,
label: 'Филтрация блок 11',
backgroundColor: 'rgba(0, 200, 1, 1)',
borderColor: 'rgba(0, 101,1, 0.75)',
hoverBackgroundColor: 'rgba(200, 200, 200, 1)',
hoverBorderColor: 'rgba(50, 50, 50, 1)',
data: Gfilblok11,
hidden: true
},
{
fill: false,
label: 'КВН',
backgroundColor: 'rgba(30, 100, 100, 1)',
borderColor: 'rgba(100, 200,1, 0.75)',
hoverBackgroundColor: 'rgba(101, 200, 200, 1)',
hoverBorderColor: 'rgba(50, 50, 50, 1)',
data: Gcvn,
hidden: true
},
{
fill: false,
label: 'КДК',
backgroundColor: 'rgba(30, 100, 100, 1)',
borderColor: 'rgba(100, 200,1, 0.75)',
hoverBackgroundColor: 'rgba(101, 200, 200, 1)',
hoverBorderColor: 'rgba(50, 50, 50, 1)',
data: Gndk,
hidden: true
},
{
fill: false,
label: 'НДК',
backgroundColor: 'rgba(30, 100, 100, 1)',
borderColor: 'rgba(100, 200,1, 0.75)',
hoverBackgroundColor: 'rgba(101, 200, 200, 1)',
hoverBorderColor: 'rgba(50, 50, 50, 1)',
data: Gndk2,
hidden: true
}
]
};
$('#reset_zoom').click(function() {
barGraph.resetZoom();
})
$("#save-btn").click(function() {
$("#mycanvas").get(0).toBlob(function(blob) {
saveAs(blob, "chart_1.png");
});
});
var config = {
type: 'line',
data: chartdata,
options: {
responsive: true,
title: {
display: true,
text: 'Диаграма: Отвеси и филтрации'
},
scales: {
yAxes: [{
type: type,
scaleLabel: {
display: true,
labelString: '[ mm ] ,[ m ], [ l/s ]'
},
ticks: {
beginAtZero: false
}
}],
xAxes: [{
type: 'time',
time: {
tooltipFormat: timeFormat,
displayFormats: {
'hour': timeFormat
}
},
scaleLabel: {
display: true,
labelString: 'Дата/Час'
},
ticks: {
beginAtZero: true
}
}]
},
// Container for pan options
pan: {
// Boolean to enable panning
enabled: true,
// Panning directions. Remove the appropriate direction to disable
// Eg. 'y' would only allow panning in the y direction
mode: 'y'
},
// Container for zoom options
zoom: {
// Boolean to enable zooming
enabled: true,
// Zooming directions. Remove the appropriate direction to disable
// Eg. 'y' would only allow zooming in the y direction
mode: 'xy'
},
animation: {
duration: 2000,
onProgress: function(animation) {
progress.value = animation.currentStep / animation.numSteps;
},
onComplete: function() {
window.setTimeout(function() {
progress.value = 0;
}, 2000);
}
},
legend: {
display: true,
labels: {
//fontColor: 'rgb(255, 99, 132)'
usePointStyle: true
}
}
},
plugins: [{
beforeDraw: function(c) {
var reset_zoom = document.getElementById("reset_zoom"); //reset button
var ticks = c.scales['x-axis-0', 'y-axis-0'].ticks.length; //x-axis ticks array
var labels = c.data.labels.length; //labels array
if (ticks < labels) reset_zoom.hidden = false;
else reset_zoom.hidden = true;
}
}]
};
var type = 'linear';
var ctx = document.getElementById("mycanvas");
var barGraph = new Chart(ctx, config);
window.onload = function() {
var ctx = document.getElementById("mycanvas");
window.myLine = barGraph;
};
document.getElementById('toggleScale').addEventListener('click', function() {
type = type === 'linear' ? 'logarithmic' : 'linear';
window.myLine.options.title.text = 'Диаграма('+type+'): Отвеси и филтрации';
window.myLine.options.scales.yAxes[0] = {
display: true,
type: type
};
window.myLine.update();
}); //end data
},
error: function(data) {
console.log(data);
}
});
}
$('#search').click(function(){
var start_date = $('#start_date').val();
var end_date = $('#end_date').val();
if(start_date != '' && end_date != '')
{
getdata_chart(start_date, end_date);
}
else
{
alert('Both Date is required');
}
});
});
</script>
in to the controller:
function getdata_chart(Request $request)
{
$start_date = date('d-m-Y 00:00:00');
$end_date = date('d-m-Y 23:59:59');
if($request->start_date != '' && $request->end_date != '')
{
$dateScope = array($request->start_date ." 00:00:00", $request->end_date ." 23:59:59");
} else {
$dateScope = array($start_date, $end_date);
};
$students = otv_fil::whereBetween('timestamp', $dateScope)
->selectRaw('timestamp,blok9osx,blok9osy,blok11osx,blok11osy,filblok10,filblok11,cvn,ndk,ndk - ? as ndk2',[743.38])
->orderBy('timestamp', 'ASC')
->get();
return response()->json($students);
}
The main part need to be in search click function right?

c3.js remove empty spaces between timeseries with non consecutive days

I made a bar graph with c3.js and I need to add non consecutive days to the graph
The problem is that the graph adds empty days
http://c3js.org/samples/timeseries.html
I used this code, it is possible to copy and paste code in page and see live result
var chart = c3.generate({
data: {
x: 'x',
type: 'bar',
columns: [
['x', '2013-01-01', '2013-01-02', '2013-01-03', '2013-01-04', '2013-01-05', '2013-01-07', '2013-01-09', '2013-01-10', '2013-01-11'],
['data1', 30, 200, 100, 400, 150, 250, 250, 250, 250],
['data2', 130, 340, 200, 500, 250, 350, 250, 250, 250]
]
},
axis: {
x: {
type: 'timeseries',
tick: {
format: '%Y-%m-%d'
}
}
}
});
You can use a category axis instead of a timeseries axis. Check the example:
var chart = c3.generate({
data: {
x: 'x',
type: 'bar',
columns: [
['x', '2013-01-01', '2013-01-02', '2013-01-03', '2013-01-04', '2013-01-05', '2013-01-07', '2013-01-09', '2013-01-10', '2013-01-11'],
['data1', 30, 200, 100, 400, 150, 250, 250, 250, 250],
['data2', 130, 340, 200, 500, 250, 350, 250, 250, 250]
],
},
axis: {
x: {
type: 'category',
tick: {
centered: true
}
}
}});

AmXYChart - How to add padding to prevent hidden overflows

I have create a simple XY Chart graph with percent as y axes and customers as x axes, I randomised the data between 0...100% with a set of 184 points. and have a bit of difficulty display the lower/upper region values. I have included an image for the demonstration.
Here my config file, I cant seem to find some sort of offset/padding ?
{
type: 'xy',
addClassNames: true,
autoMargins: false,
marginLeft: 67,
marginBottom: 55,
graphs: [{
balloonFunction,
bullet: 'round',
xField: 'customers',
yField: 'rate',
bulletSize: 16,
lineColorField: 'color',
}],
valueAxes: [
{
title,
borderThickness: 0,
axisThickness: 2,
maximum: 100,
labelFunction: (e,val) => { return val + "%"; },
},
{
title,
position: 'bottom',
axisAlpha: 0,
borderThickness: 0,
axisThickness: 0,
gridThickness: 0,
},
],
dataProvider: data,
};
Thanks.
There isn't a way to pad this without modifying your minimum and maximum to be further outside your 0-100 range to accommodate. Since you're using a labelFunction, you can set it up so that you don't display any labels above and below 0-100% if you want, for example:
labelFunction: (e, val) => { return (val > 100 || val < 0 ? "" : val + "%"); }
Demo below using -10 as a minimum and 110 as a maximum:
var data = [{"rate": 99, "customers": 2421},{"rate": 76,"customers": 100},{"rate": 68,"customers": 1711},{"rate": 38,"customers": 313},{"rate": 94,"customers": 393},{"rate": 57,"customers": 946},{"rate": 99,"customers": 1772},{"rate": 20,"customers": 2168},{"rate": 100,"customers": 754},{"rate": 40,"customers": 121},{"rate": 51,"customers": 2412},{"rate": 15,"customers": 2364},{"rate": 32,"customers": 2161},{"rate": 55,"customers": 1506},{"rate": 29,"customers": 986},{"rate": 0,"customers": 698},{"rate": 4,"customers": 1285},{"rate": 22,"customers": 2108},{"rate": 17,"customers": 2081},{"rate": 79,"customers": 251},{"rate": 48,"customers": 258},{"rate": 41,"customers": 1541},{"rate": 35,"customers": 1132},{"rate": 86,"customers": 1213},{"rate": 1,"customers": 1936},{"rate": 51,"customers": 1737},{"rate": 5,"customers": 2447},{"rate": 60,"customers": 305},{"rate": 37,"customers": 776},{"rate": 64,"customers": 886}];
var chart = AmCharts.makeChart("chartdiv", {
type: 'xy',
addClassNames: true,
autoMargins: false,
marginLeft: 67,
marginBottom: 55,
graphs: [{
//balloonFunction,
bullet: 'round',
xField: 'customers',
yField: 'rate',
bulletSize: 16,
lineAlpha: 0, //for testing only
lineColorField: 'color',
}],
valueAxes: [
{
title: "Rate (%)",
borderThickness: 0,
axisThickness: 2,
maximum: 110,
minimum: -10,
labelFunction: (e,val) => { return (val > 100 || val < 0 ? "" : val + "%"); },
},
{
title: "Customers",
position: 'bottom',
axisAlpha: 0,
borderThickness: 0,
axisThickness: 0,
gridThickness: 0,
},
],
dataProvider: data,
});
<script type="text/javascript" src="//www.amcharts.com/lib/3/amcharts.js"></script>
<script type="text/javascript" src="//www.amcharts.com/lib/3/xy.js"></script>
<div id="chartdiv" style="width: 100%; height: 300px;"></div>
If you want to remove the extra grid lines from the additional points generated by the new minimum and maximum, you'll have to use guides as your grid lines and labels instead of the ones auto-generated by the chart. For example:
valueAxes: [{
guides: [{
"value": 0,
"label": "0%",
"lineAlpha": .2,
"tickLength": 5
},
// repeat for each tick/grid line
],
"gridAlpha": 0,
"tickLength": 0,
"labelsEnabled": false,
// ...
Demo:
var data = [{"rate": 99, "customers": 2421},{"rate": 76,"customers": 100},{"rate": 68,"customers": 1711},{"rate": 38,"customers": 313},{"rate": 94,"customers": 393},{"rate": 57,"customers": 946},{"rate": 99,"customers": 1772},{"rate": 20,"customers": 2168},{"rate": 100,"customers": 754},{"rate": 40,"customers": 121},{"rate": 51,"customers": 2412},{"rate": 15,"customers": 2364},{"rate": 32,"customers": 2161},{"rate": 55,"customers": 1506},{"rate": 29,"customers": 986},{"rate": 0,"customers": 698},{"rate": 4,"customers": 1285},{"rate": 22,"customers": 2108},{"rate": 17,"customers": 2081},{"rate": 79,"customers": 251},{"rate": 48,"customers": 258},{"rate": 41,"customers": 1541},{"rate": 35,"customers": 1132},{"rate": 86,"customers": 1213},{"rate": 1,"customers": 1936},{"rate": 51,"customers": 1737},{"rate": 5,"customers": 2447},{"rate": 60,"customers": 305},{"rate": 37,"customers": 776},{"rate": 64,"customers": 886}];
var chart = AmCharts.makeChart("chartdiv", {
type: 'xy',
addClassNames: true,
autoMargins: false,
marginLeft: 67,
marginBottom: 55,
graphs: [{
//balloonFunction,
bullet: 'round',
xField: 'customers',
yField: 'rate',
bulletSize: 16,
lineAlpha: 0, //for testing only
lineColorField: 'color',
}],
valueAxes: [
{
title: "Rate (%)",
borderThickness: 0,
axisThickness: 2,
maximum: 110,
minimum: -10,
guides: [{
value: 0,
label: "0%",
lineAlpha: .2,
tickLength: 5
},{
value: 20,
label: "20%",
lineAlpha: .2,
tickLength: 5
},{
value: 40,
label: "40%",
lineAlpha: .2,
tickLength: 5
},{
value: 60,
label: "60%",
lineAlpha: .2,
tickLength: 5
},{
value: 80,
label: "80%",
lineAlpha: .2,
tickLength: 5
},{
value: 100,
label: "100%",
lineAlpha: .2,
tickLength: 5
}],
gridAlpha: 0,
tickLength: 0,
labelsEnabled: false
},
{
title: "Customers",
position: 'bottom',
axisAlpha: 0,
borderThickness: 0,
axisThickness: 0,
gridThickness: 0,
},
],
dataProvider: data,
});
<script type="text/javascript" src="//www.amcharts.com/lib/3/amcharts.js"></script>
<script type="text/javascript" src="//www.amcharts.com/lib/3/xy.js"></script>
<div id="chartdiv" style="width: 100%; height: 300px;"></div>

Exclude zero values from a C3.js bar chart

Let's take for example following chart http://c3js.org/samples/chart_bar.html
but replace columns data with the data below:
var chart = c3.generate({
data: {
columns: [
['data1', 30, 0, 100, 0, 150, 250],
['data2', 130, 0, 140, 200, 0, 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({
columns: [
['data3', 130, -150, 200, 300, -200, 100]
]
});
}, 1000);
As we see we have a lot of white space or ZERO value bars, how can we remove it and remove white space. (not hide, I know how to hide it with CSS)
Image example, what should be removed
as googled in https://github.com/c3js/c3/issues/81
you need replace 0 to 'null' and add this:
line: {
connectNull: true,
},
var chart = c3.generate({
data: {
columns: [
['data1', 30, null, 100, null, 150, 250],
['data2', 130, null, 140, 200, null, 50]
],
line: {
connectNull: true,
},
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({
columns: [
['data3', 130, -150, 200, 300, -200, 100]
]
});
}, 1000);
Just add
line: {
connectNull: true,
}
in your c3.generate block.
It will connect all points/bars/... on the chart with a zero value in between.
It works with null as well as with 0.

Resources