Rotated bar chart data label format - javascript

I am trying to format the data label I have on this rotated x axis bar chart found here: http://jsfiddle.net/blackrimsolutions/01bqmbws/
If I only put:
labels: true
It shows the label but not formatted in percentages.
If I call the labels array:
labels: {
format: {
data1: d3.format('%'),
data2: d3.format('%'),
data3: d3.format('%'),
data4: d3.format('%'),
data5: d3.format('%'),
data6: d3.format('%'),
data7: d3.format('%'),
data8: d3.format('%'),
data9: d3.format('%'),
data10: d3.format('%')
}
}
The data labels go away.
I can't have both label: true and the array. I have tried several other ways to get it to work but it mainly seems to not work on rotated axis.
It works on this chart:
var chart1 = c3.generate({
bindto: "#chart1",
padding: {
top: 20,
right: 40,
left: 40
},
data: {
x: 'x',
columns: [
['x', '2013', '2014'],
['data1', 0, 0],
['data2', 0, 0]
],
names: {
data1: 'Sales Growth',
data2: 'Trans Growth'
},
type: 'bar',
labels: {
format: {
data1: d3.format('%'),
data2: d3.format('%')
}
}
},
grid: {
y: {
show: true
}
},
transition: {
duration: 2000
},
bar: {
width: {
ratio: 0.5
}
},
axis: {
y: {
tick: {
format: d3.format('%')
}
},
x: {
type: 'category',
tick: {
rotate: 0,
multiline: false
},
centered: true,
height: 30
}
},
color: {
pattern: ['#A2AD00', '#FEB612', '#00A9ED', '#004165', '#F79447', '#C01324', '#FB4F14']
},
tooltip: {
show: false
}
});
But that's it. Any advice is greatly appreciated.
Thanks!!

I was able to successfully format all of the data sets using the format function built in to C3.js, and with the help of a javascript rounding answer here on Stack.
The format for the function is:
format: function (v, id, i, j) { ... }
v is the value of the data point where the label is shown.
id is the id of the data where the label is shown.
i is the index of the data point where the label is shown.
j is the sub index of the data point where the label is shown.
Here is my final labels code:
labels: {
format: function (v) {
'use strict';
var percent = (Math.round((v * 1000) / 10) / 100);
return (percent * 100).toFixed(2) + '%';
}
}
Thanks everyone!

Related

ChartJS options.scales is being completely ignored

I am trying to make a chart which has years along the x-axis and dollar amounts along the y-axis. I finally got close to what I'm looking for, but I found that because the x coordinates are numbers, ChartJS is putting commas in them which looks really strange for years.
After some digging, I used the callbacks. options.plugin.tooltip.callbacks.label worked to let me remove commas in the tooltips, but when I use options.scales.x[0].ticks.callback to try to fix the labels on the bottom, not only does it not work, but I don't see the console.log statement in their ever being printed so it seems it's not even calling the callback. I've tried several variations of how to do the callback based on what I found online and on Stack Overflow which I think correspond to the different ways ChartJS did this in different versions. (I'm on version 3.5.1.)
Then, I realized that... none of the options under options.scales appear to have any effect. I change the min, the title, the tick settings (color to red, callback, etc.) and it has no effect. (This also explains why I was having trouble when using the line chart and had to switch to scatter; apparently type: 'linear' wasn't being picked up nor did it do anything different when I set it to type: 'date' or whatever the exact working was for that.)
Meanwhile, the other options like options.showLine or options.elements do have an effect and I'm seeing the chart and not getting any errors in the console. So, it is picking up the options, just ignoring everything I have in options.scales.
Here is the relevant code:
// Sample data added to make this example self-contained
// This is my internal data format
let data = {
"Series1": [ {x: 2001, y: 100 }, {x: 2002, y: 110 }, {x: 2003, y: 107 }, ],
"Series2": [ {x: 2001, y: 107 }, {x: 2002, y: 102 }, {x: 2004, y: 95 }, ],
}
// Define data //////////////////////////////////////////////////////
// I convert data to format ChartJS wants and add a few options
let datasets = [];
for(let label in data) {
let c = colorIterator.next().value
datasets.push({
label: label,
data: data[label],
backgroundColor: c,
borderColor: c,
});
}
// Define options //////////////////////////////////////////////////////
let chartConfig = {
type: 'scatter',
data: { datasets: datasets, },
options: {
title: { display: false },
indexAxis: 'x', responsive: true, maintainAspectRatio: false,
showLine: true,
elements: {
line: { display: true, tension: 0, borderWidth: 1, fill: false, },
point: { radius: 3 }
},
interaction: { mode: 'x', },
scales: {
x: [{
type: 'linear',
min: 1995, max: (new Date()).getFullYear()+1, stepSize: 1,
title: { display: true, text: 'Year' },
ticks: {
display: true,
major: { enabled: true },
color: 'red',
callback: function(value, index, ticks) {
console.log(value);
return Chart.Ticks.formatters.numeric.apply(this, [value, index, ticks])
.replace(",","");
}
}
}],
y: [{
title: { display: true, text: '$' },
ticks: {
display: true,
color: 'red',
},
}],
},
plugins: {
tooltip: {
callbacks: {
label: function(context) {
let label = context.dataset.label || '';
if(label) {
let x = context.label.replace(",","");
let y = context.formattedValue;
return 'Year ' + x + ' "' + label + '": $' + y;
} else { return 'x'; }
},
},
},
},
}
};
// MAKE CHART //////////////////////////////////////////////////////
let mainChart = new Chart(document.getElementById(c.id), chartConfig);
As described in the docs the scales are not arrays. All the scales are objects in the scale object.
So you will need to change your code to this:
options: {
scales: {
x: {
// x options
},
y: {
// y options
},
}
}

C3 js: Is it possible to align 2 points from end to end?

this is my first question here in stack overflow.
I'm working with C3 and I'm wondering if is possible to align 2 points from end to end.
for example if in my chart I have 100 and another point -100, but I want to pass through the columns that appears in the image.
let me show you what I want:
I want to join/align the two-point that appears in the circle highlighted:
here is my code:
var chart = c3.generate({
data: {
columns: [
["data1", 30, 200, 100, 400, 150, 250],
["data2", -100],
["data3", null, null, null, null, null, 100],
],
axis: {
y: {
max: 365,
min: 335,
},
},
type: "bar",
types: {
data2: "line",
data3: "line",
},
colors: {
data1: "#f567",
data2: "blue",
},
bar: {
width: {
ratio: 0.5, // this makes bar width 50% of length between ticks
},
},
labels: {
format: function (v, id, i, j) {
return v;
},
},
// or
//width: 100 // this makes bar width 100px
},
});
thank you for your help! :)
I just added this part and it works
line: {
connectNull: true
},

Is there a way to scale c3.js graph if the data is small?

I have data to display on c3.js graph and there is one piece of data which is smaller than other ones.
For exmaple A can by 140 000, B 20 000 and C 700. C can even be negative.
The problem is that when I display my data on the chart you can't really see the dynamics of C because its' values are too little for scale of the graph. If C is negative it doesn't show on the graph at all.
Is there some way to scale the graph that way so all data displayed properly?
const chartConfig = {
bindto: $element.find('.canvas')[0],
data: {
json: [],
keys: { value: [] },
type: 'line'
},
grid: {
x: {
get: getXGrid
}
},
axis: {
y: { min: 0 },
x: {
tick: {
culling: false,
format: formatXAxis
}
},
y2: {
padding: {top: 0, bottom: 0},
min : 0,
max : 100,
tick : {
format: (value) => `${value}%`
}
}
}
};
Later in one of my methods I set Y max to be the biggest number in data.
chartConfig.axis.y.max = getRoundMax(chartConfig.data);
UPD link
You must be looking for logarithmic scale.
At this moment c3.js does not support for it out-of-the-box.
But there are some workarounds at github:
First, they convert values:
data_test_original = ['data1', 140000, 20000, 700, 10, 100, 1000, 3, 500, 50, 5, 3000]
data_test = ['data1'];
for(var i=1; i<data_test_original.length; i++){
data_test[i] = Math.log(data_test_original[i]) / Math.LN10;
}
Then, they use it alongside with adjusted Y-axis:
c3.generate({
data: {
...
columns: [ data_test ]
},
...
axis : {
y : {
tick: {
format: function (d) { return Math.pow(10,d).toFixed(0); }
}
}
}
});
See full example here or there. Hope this will suit your needs.

Add click event on each category name on X axis in c3 js

I'm using c3 js for generating categories bar chart
Here is code
var obj = {
size: {
height: 200,
},
bindto: '#grBarChart',
data: {
columns: data.columns,
type: "bar"
},
color: {
pattern: ['#c90000', '#008cba', '#FAAC3D','#427322', '#9ead9b', '#ffa500']
},
axis: {
x: {
type: 'category',
categories: data.categories,
label: {
text: 'Scanned Groups',
position: 'outer-center'
}
},
y: {
label: {
text: 'Count (Rules)',
position: 'outer-middle'
}
}
},
bar: {
width: {
ratio: 0.5,
}
},
grid: {
y: {
show: true
}
}
};
var chart = c3.generate(obj);
This code is generating the following graph
Now my problem is I'm not able to add click event on X Axis Category Names ( Logging 11, Data Protection 13 ...)
I referred C3 Documentation but not able to solve my problem.
Please give me your thought?

C3 graph overlapping x-axis label

C3 graph overlap x-axis labels which is in date time format. I have googled this query but didn't get any solution for it.Is it possible that c3 only shows couple of date time rather then showing altogether which result in overlap x-axis labels
var data = {
x: 'x',
xFormat:'%Y-%m-%d/%H:%M',
empty: {
label: {
text: "No Data"
}
},
columns: [
['x', '{$dateArray}'],
['Attack', {$data}],
],colors: {
Attack: '#67b7dc',
},
types: {
Attack: 'area'
}};
var chart = c3.generate({bindto: '#chart1',
size: {
height: 630,
},
data: data,
grid: {
x: {
show: true
},
y: {
show: true
}
},
tooltip: {
format: {
value: function (value, ratio, id) {
var format = value+' Gbps [ IP: '+destIp[value]+' ]';
return format;
}
}
},
zoom: {
enabled: true
},
subchart: {
show: true
},axis: {
x: {
type: 'timeseries',
tick: {
format: '%b %d, %H:%M',
rotate: 90,
multiline: false
}
},
y: {
tick: {
format: function (d) {
return d.toFixed(3);
}
},
label: {
text: 'Attack Size ( Gbps )',
position: 'outer-middle'
}
}
}
});
Use c3.js chart config tick.count, set it to desired integer value like 2,3 or 4.
Use c3.js Timeseries Chart exmaple to play with this config.
Problem without tick.count:-
Problem solved with tick.count config:-

Categories