c3 categories tick formatting - javascript

I have a c3 bar graphing categories. I'd like to format the category label to be able to truncate it to a certain length. But i can't figure it out.
Here is the graph definition:
var chart;
chart = c3.generate({
padding: {
top: 20,
bottom: 20
},
data: {
columns: [
["Listeners",4,2,0],
["Listens",4,2,0]],
type: 'bar',
groups:[["Listeners", "Listens"]]
},
axis: {
x: {
type: 'category',
categories: ["012345678890", "012345678890", "012345678890"],
}
},
bar: {
width: {
ratio: 0.5 // this makes bar width 50% of length between ticks
}
},
legend: {
show: false
}
});
<link href="https://raw.githubusercontent.com/c3js/c3/0.4.11/c3.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://raw.githubusercontent.com/c3js/c3/0.4.11/c3.js"></script>
<div id="chart" class="c3" style="max-height: 280px; position: relative;"></div>
I tried adding this to format the tick inside the x axis definition, but it complains that chart is not defined
tick:{format:function (x) { return chart.categories()[x].substring(0, 10); }}
Thanks in advance!

Of course, you just declare the variable var chart; that has no value, is undefined.
Try to create the chart config before the function c3.generate() then pass the config as argument.
var config = {
padding : {
top : 20,
bottom : 20
},
data : {
columns : [ [ "Listeners", 4, 2, 0 ], [ "Listens", 4, 2, 0 ] ],
type : 'bar',
groups : [ [ "Listeners", "Listens" ] ]
},
axis : {
x : {
type: 'category',
categories: ["012345678890", "012345678890","012345678890"],
}
},
bar : {
width : {
ratio : 0.5
}
},
legend : {
show : false
}
};
config.axis.x.tick = {
format : function(x) {
return config.axis.x.categories[x].substring(0,10)
}
};
var chart = c3.generate(config);

In your code, you have named categories in the x-axis definition, I'm not sure why you wouldn't just change the labels?
** EXAMPLE **
var chart;
chart = c3.generate({
padding: {
top: 20,
bottom: 20
},
data: {
columns: [
["Listeners",4,2,0],
["Listens",4,2,0]],
type: 'bar',
groups:[["Listeners", "Listens"]]
},
axis: {
x: {
type: 'category',
_comment: "THIS IS WHERE YOU SET YOUR CATEGORY LABELS",
categories: ["Label1", "Label2", "Label3"],
}
},
bar: {
width: {
ratio: 0.5 // this makes bar width 50% of length between ticks
}
},
legend: {
show: false
}
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.11/c3.min.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.11/c3.min.js"></script>
<div id="chart" class="c3" style="max-height: 280px; position: relative;"></div>

Related

How to provide different labels in chart.js for toolbox and axis

I've provide a simple line chart with chart.js 3.7.0. How can I provide different labels for axis and toolbox? In my example I like to give empty lables besides 3 special values for the axis but the exact date value in the toolbox of a point.
My build:
<script>
chartLabels = ['2 years ago','', ... , '','1 year ago','', ... ,'','Today'];
chartData = [0,0, ... ,0,0.13,0.08, ... ,0,0.1];
yMax = 3;
</script>
<canvas id="chart-myvalues" width="160" height="90"></canvas>
In JS additionally:
const data = {
labels: chartLabels,
datasets: [{
label: 'My Value XYZ',
data: chartData,
tension: 0.5,
}]
};
const config = {
type: 'line',
data: data,
options: {
plugins: {
legend: {
display: false
}
},
scales: {
x: {
grid: {
display: false
},
ticks: {
autoSkip: false,
maxRotation: 0,
minRotation: 0
}
},
y: {
min: 0,
max: yMax,
grid: {
display: false
}
}
}
}
};
new Chart('chart-myvalue',config);
As asked for here is what I want exactly: In the screenshot above you see the 1 year ago once on the x axis and in the toolbox. On the x axis it is like I want it to. In the Toolbox I like to see the exact date of that value xyz (I can provide the date but I need to know how to provide different labels in chart.js for toolbox and axis)
It's called a tooltip and you can read more about it here. Basically, you have to make a callback to the title and label to change the x-axis and y-axis of the tooltip respectively. Here's how it would look:
boxLabels = ['2020-05-26', '2020-08-26', '2020-11-26', '2021-02-26', '2021-05-26', '2021-08-26', '2021-11-26', '2022-02-26', '2022-05-26'];
options: {
plugins: {
tooltip: {
callbacks: {
title: function(context) {
let title = context[0].label || boxLabels[context[0].dataIndex];
return title;
},
label: function(context) {
let label = context.dataset.label + ": " + context.dataset.data[context.datasetIndex];
return label;
}
}
}
}
};
Note that context for title returns an array, so you have to index it to get the element. See the snippet bellow for a whole example.
chartLabels = ['2 years ago','','','','1 year ago','','','','Today'];
chartData = [0,0,0,0,0.13,0.08,0,0,0.1];
yMax = 3;
boxLabels = ['2020-05-26', '2020-08-26', '2020-11-26', '2021-02-26', '2021-05-26', '2021-08-26', '2021-11-26', '2022-02-26', '2022-05-26'];
const data = {
labels: chartLabels,
datasets: [{
label: 'My Value XYZ',
data: chartData,
tension: 0.5,
}]
};
const config = {
type: 'line',
data: data,
options: {
plugins: {
legend: {
display: false
},
tooltip: {
callbacks: {
title: function(context) {
let title = context[0].label || boxLabels[context[0].dataIndex];
return title;
},
label: function(context) {
let label = context.dataset.label + ": " + context.dataset.data[context.datasetIndex];
return label;
}
}
},
},
scales: {
x: {
grid: {
display: false
},
ticks: {
autoSkip: false,
maxRotation: 0,
minRotation: 0
}
},
y: {
min: 0,
max: yMax,
grid: {
display: false
}
}
}
}
};
new Chart('chart-myvalues',config);
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" type="text/css" href="styles.css">
</head>
<body>
<canvas id="chart-myvalues" width="160" height="90"></canvas>
<script src="https://cdn.jsdelivr.net/npm/chart.js#3.7.1/dist/chart.min.js"></script>
</body>
</html>

Json data for apexcharts

I have some problems rendering some data from a JSON in my apexchart series.
Here is the example of my chart with the data that I want to be in my JSON, and i don't know how to write it.
var _seed = 42;
Math.random = function() {
_seed = _seed * 16807 % 2147483647;
return (_seed - 1) / 2147483646;
};
var options = {
series: [{
name: "Q",
data: [0, 4800, 9500, null],
},
{
name: "Q - 1",
data: [0, 6500, 12000, 16000]
},{
name: "Q Target",
data: [15500, 15500, 15500, 15500]
},
],
chart: {
height: 350,
type: 'line',
zoom: {
enabled: false
}
},
dataLabels: {
enabled: false
},
stroke: {
curve: 'straight'
},
title: {
text: 'Clicks',
align: 'left'
},
grid: {
row: {
colors: ['#f3f3f3', 'transparent'], // takes an array which will be repeated on columns
opacity: 0.5
},
},
xaxis: {
categories: [' ', 'Month1', 'Month2', 'Month3'],
}
};
var chart = new ApexCharts(document.querySelector("#chart"), options);
chart.render();
#chart {
max-width: 450px;
margin: 35px auto;
}
<script src="https://cdn.jsdelivr.net/npm/promise-polyfill#8/dist/polyfill.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/eligrey-classlist-js-polyfill"></script>
<script src="https://cdn.jsdelivr.net/npm/findindex_polyfill_mdn"></script>
<script src="https://cdn.jsdelivr.net/npm/es6-promise#4/dist/es6-promise.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/es6-promise#4/dist/es6-promise.auto.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
<div id="chart"></div>
If someone could give me a hint, is kindly appreciated.
The JSON looks like this , for retrieving data for the apexchart
{
"data_clicks":[
{
"name":"Q",
"data":[
{
"x":" ",
"y":0
},
{
"x":"Month1",
"y":2400
},
{
"x":"Month2",
"y":5200
},
{
"x":"Month3",
"y":null
}
]
},
{
"name":"Q - 1",
"data":[
{
"x":" ",
"y":0
},
{
"x":"Month1",
"y":1800
},
{
"x":"Month2",
"y":7150
},
{
"x":"Month3",
"y":10200
}
]
},
{
"name":"Q Target",
"data":[
{
"x":" ",
"y":11000
},
{
"x":"Month1",
"y":11000
},
{
"x":"Month2",
"y":11000
},
{
"x":"Month3",
"y":11000
}
]
}
],

C3js horizontal bar chart labels cut off and sizing issue

I have a fixed size horizontal bar chart with rather long labels.
Main Question:
The label with the biggest data always gets cut off.
Additional Question (only nice to have.. ;) Is it possible in C3 to add margin between the bars?
Example with labels been cut off:
var colors = ['#0065A3', '#767670', '#D73648', '#7FB2CE', '#00345B'];
var padding = 5;
data= [
['veryveryveryveryverylongdatalabel01', 439034],
['veryveryveryveryverylongdatalabel02', 413664],
['veryveryveryveryverylongdatalabel03', 351376],
['veryveryveryveryverylongdatalabel04', 349932],
['veryveryveryveryverylongdatalabel05', 316490],
['veryveryveryveryverylongdatalabel06', 315039],
['veryveryveryveryverylongdatalabel07', 285908],
['veryveryveryveryverylongdatalabel08', 285681],
['veryveryveryveryverylongdatalabel09', 285215],
['veryveryveryveryverylongdatalabel10', 203248],
['veryveryveryveryverylongdatalabel11', 200508],
['veryveryveryveryverylongdatalabel12', 195508],
['veryveryveryveryverylongdatalabel13', 195058],
['veryveryveryveryverylongdatalabel14', 193508],
['veryveryveryveryverylongdatalabel15', 185508],
['veryveryveryveryverylongdatalabel16', 180508],
['veryveryveryveryverylongdatalabel17', 177508]
];
var totalDataValue = 0
data.forEach(function(d){
totalDataValue+=d[1];
});
var chart1 = c3.generate({
bindto: d3.select('#chart1'),
data: {
columns: data,
type: 'bar',
labels: {format : function(v, id) {return id + ": " + d3.format(",.0f")(v) + " ["+d3.format(".2%")(v/totalDataValue)+"]"; }}
},
bar: {
width: { ratio: 1}
},
legend: {
show: false,
},
tooltip: {
show: true,
format: {
value: function(value) {
return d3.format(",.0f")(value);
}
}
},
zoom: {
enabled: true
},
axis: {
x: {
show:false,
type:'category',
categories: ['value1']
},
y: {
show:false
},
rotated: true
}
});
#chart1 {
width: 600px;
height: 400px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/c3/0.7.10/c3.min.css" rel="stylesheet" />
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.7.10/c3.min.js"></script>
<div id="chart1" class "c3">
</div>
It seems to be an internal C3 sizing issue.
Am I right there?
Is there a way to prevent the labels from beeing cut off?
thank you
You can set Y Axis top padding.
axis: {
y: {
padding : {
top: 430
}
},
rotated: true
}
You can also calculate top padding value based on length of largest label.
You could add an empty space by using a couple of "\u00A0" at the end of your labels format function:
data: {
labels: {format : function(v, id) {return id + ": " + d3.format(",.0f")(v)
+ " ["+d3.format(".2%")(v/totalDataValue)+"]"+"\u00A0\u00A0\u00A0\u00A0\u00A0"; }}
},
To set some space between the bars, add the bar.space parameter:
bar: {
space: 0.2
}
Below the code sipped:
var colors = ['#0065A3', '#767670', '#D73648', '#7FB2CE', '#00345B'];
var padding = 5;
data= [
['veryveryveryveryverylongdatalabel01', 439034],
['veryveryveryveryverylongdatalabel02', 413664],
['veryveryveryveryverylongdatalabel03', 351376],
['veryveryveryveryverylongdatalabel04', 349932],
['veryveryveryveryverylongdatalabel05', 316490],
['veryveryveryveryverylongdatalabel06', 315039],
['veryveryveryveryverylongdatalabel07', 285908],
['veryveryveryveryverylongdatalabel08', 285681],
['veryveryveryveryverylongdatalabel09', 285215],
['veryveryveryveryverylongdatalabel10', 203248],
['veryveryveryveryverylongdatalabel11', 200508],
['veryveryveryveryverylongdatalabel12', 195508],
['veryveryveryveryverylongdatalabel13', 195058],
['veryveryveryveryverylongdatalabel14', 193508],
['veryveryveryveryverylongdatalabel15', 185508],
['veryveryveryveryverylongdatalabel16', 180508],
['veryveryveryveryverylongdatalabel17', 177508]
];
var totalDataValue = 0
data.forEach(function(d){
totalDataValue+=d[1];
});
var chart1 = c3.generate({
bindto: d3.select('#chart1'),
data: {
columns: data,
type: 'bar',
labels: {format : function(v, id) {return id + ": " + d3.format(",.0f")(v) + " ["+d3.format(".2%")(v/totalDataValue)+"]"+"\u00A0\u00A0\u00A0\u00A0\u00A0"; }}
},
bar: {
width: { ratio: 1},
space: 0.2
},
legend: {
show: false,
},
tooltip: {
show: true,
format: {
value: function(value) {
return d3.format(",.0f")(value);
}
}
},
zoom: {
enabled: true
},
axis: {
x: {
show:false,
type:'category',
categories: ['value1']
},
y: {
show:false
},
rotated: true
}
});
#chart1 {
width: 600px;
height: 400px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/c3/0.7.10/c3.min.css" rel="stylesheet" />
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.7.10/c3.min.js"></script>
<body>
<br><br>
<div id="chart1" class "c3">
I found a solution for preventing the labels from being cut-off.
Please see my following post on this:
Calculate padding for C3js horizontal bar charts
It's based on using global chart padding instead of using y-axis padding and turning off clip-path

Gap between bars C3.js

I want to put gaps between bars.
I tried ;
...
bar:{
width: {
ratio: 0.5
}
},
...
The code above didn't work for me.
The question is: why doesn't it work or how can I make it work?
Try some thing like:
var colors = ['#1f77b4', '#aec7e8', '#ff7f0e'];
var chart = c3.generate({
bindto: '#chart',
data: {
columns: [
['value: ', 20, 14, 3]
],
type: 'bar',
labels: true,
color: function(color, d) {
return colors[d.index];
}
},
axis: {
x: {
type: 'category',
categories: ['cat1', 'cat2', 'cat3']
}
},
bar: {
width: {
ratio: 0.5,
}
},
grid: {
focus: {
show: false
}
}
});
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/c3/0.4.5/c3.min.css" />
</head>
<body>
<div id="chart"></div>
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.4.6/d3.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/c3/0.4.5/c3.min.js"></script>
</body>
</html>

Make simple bar chart using C3 with separate columns on the x axis

I'm trying to create a bar chart using C3 and D3 but I'm having trouble getting the columns to be unrelated to each other, other than for the fact that they use the same scale on the Y-axis.
I've included images to better explain.
var chart = c3.generate({
bindto: '#designerChart',
data: {
columns: [
['MA', 6],
['ME', 8],
['NY', 6],
['CN', 5],
['TX', 2]
],
type: 'bar',
},
axis: {
y: {
max: 10,
min: 0,
padding: { top: 0, bottom: 0 }
}
}
});
Results in a group of bars and when I hover over them I get the details for all the bars - not what I want.
I can change the data, so that it displays separate columns, but they are the same color and when I want to transition it to a pie chart you can't distinguish between the states.
var chart = c3.generate({
bindto: '#designerChart',
data: {
x: 'x',
columns: [
['x','MA', 'ME', 'NY', 'CN', 'TX'],
['rainfall', 6, 8, 6, 5, 4 ]
],
type: 'bar',
},
axis: {
x: {
type: 'category'
},
y: {
max: 10,
min: 0,
padding: { top: 0, bottom: 0 }
}
}
});
This is what I want:
Bar chart solution:
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.16.0/d3.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/c3/0.7.20/c3.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.7.20/c3.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>C3 Bar Chart</title>
</head>
<body>
<div id="designerChart"></div>
<script type="text/javascript" charset="utf-8">
$(document).ready(function() {
columnColors = ['#9a4d6f', '#c76c47', '#f85115', '#d9b099', '#d4ba2f'];
function setColumnBarColors(colors, chartContainer) {
$('#' + chartContainer + ' .c3-chart-bars .c3-shape').each(function(index) {
this.style.cssText += 'fill: ' + colors[index] + ' !important; stroke: ' + colors[index] + '; !important';
});
$('#' + chartContainer + ' .c3-chart-texts .c3-text').each(function(index) {
this.style.cssText += 'fill: ' + colors[index] + ' !important;';
});
}
var chart = c3.generate({
bindto: '#designerChart',
data: {
columns: [
['rainfall', 6, 8, 6, 5, 4]
],
type: 'bar'
},
axis: {
x: {
label: {
text: 'States',
position: 'outer-center',
},
type: 'category',
categories: ['MA', 'ME', 'NY', 'CN', 'TX'],
tick: {
centered: true
}
},
y: {
label: {
text: 'Rainfall (inches)',
position: 'outer-middle'
},
max: 10,
min: 0,
padding: {
top: 0,
bottom: 0
}
}
},
legend: {
show: false
}
});
setColumnBarColors(columnColors, 'designerChart');
// Color turns to original when window is resized
// To handle that
$(window).resize(function() {
setColumnBarColors(columnColors, 'designerChart');
});
});
</script>
</body>
</html>
Colors turn to original in this fiddle (Full Page). But it changes colors as aspected on working local files , and local references of c3 , d3 ,and jquery.
References:
setColumnBarColors function:
jzcor...#gmail.com
https://groups.google.com/forum/
http://c3js.org/gettingstarted.html
http://c3js.org/samples/axes_x_tick_format.html
http://c3js.org/reference.html

Categories

Resources