How to draw Normalize Stack chart using C3 chart? - c3.js

I want to draw normalize chart using C3 Chart library.
my current code is
var chart = c3.generate({
bindto: '#column-chart-main',
size: {
height: $('.chart-area').height()
},
data: {
rows:
chartFinalData
,
type: 'bar',
labels: {
format: d3.format('%')
},
colors: chartFinalColors,
transition: {
duration: 100
}
},
zoom: {
enabled: true
},
axis: {
y: {
show: false,
max: 1,
min: 0,
padding: {bottom:0}
},
x: {
type: 'category',
categories: chartFinalBrands
},
rotated: setChartType
},
tooltip: {
format: {
value:d3.format('%')
}
},
legend: {
show: $scope.chartTrans.showHideLegends,
position: 'inset',
inset: {
anchor: legendPosition,
x: 10,
y: 10,
step: legendSteps,
}
}
});
Above code generate simple bar stack chart.
but i need normalize bar stack chart
my current chart is - current-chart
i need chart as per - required-chart
Thanks in advance

If you want a normalised stack bar chart then you need to normalise the data first, c3 doesn't have a chart setting itself to work that out
e.g.
var data = [
['data1', 30, 200, 200, 400, 150, 250],
['data2', 130, 100, 100, 200, 150, 50],
['data3', 230, 200, 200, 300, 250, 250]
]
;
// Normalise
var scount = data.length;
for (var n = 1; n < data[0].length; n++) {
var total = 0;
for (var m = 0; m < scount; m++) {
total += data[m][n];
}
var ratio = 1.0 / total;
for (var m = 0; m < scount; m++) {
data[m][n] *= ratio;
}
}
var chart = c3.generate({
data: {
columns: data,
type: 'bar',
groups: [
['data1', 'data2', 'data3']
]
},
tooltip: {
format: {
value:d3.format('%')
}
},
axis : {
y : {
//max: 0.95, // for some reason this shows the last tick y as 100%, while 1.0 makes the last y tick 110%, don't know why
// thanks to a.n.onymous who figured out this worked better
max: 1,
padding: 0,
tick: {
format: d3.format("%")
}
}
}
});
http://jsfiddle.net/697p6hw5/6/

Related

How to create gauge diagram with amchart 5 with arabic text in it

I want to create a gauge diagram with amcharts 5 with persian text on it. All the code sample I found is working correctly with english text on it. But when I want to use persian or arabic text (rtl languages), it doesn't show texts correct. How can I solve this problem?
Here is my code:
<script>
var root = am5.Root.new("chartdiv");
root.setThemes([
am5themes_Animated.new(root)
]);
var chart = root.container.children.push(am5radar.RadarChart.new(root, {
panX: false,
panY: false,
startAngle: 160,
endAngle: 380
}));
var axisRenderer = am5radar.AxisRendererCircular.new(root, {
innerRadius: -40
});
axisRenderer.grid.template.setAll({
stroke: root.interfaceColors.get("background"),
visible: true,
strokeOpacity: 0.8
});
var xAxis = chart.xAxes.push(am5xy.ValueAxis.new(root, {
maxDeviation: 0,
min: -40,
max: 100,
strictMinMax: true,
renderer: axisRenderer
}));
var axisDataItem = xAxis.makeDataItem({});
var clockHand = am5radar.ClockHand.new(root, {
pinRadius: am5.percent(20),
radius: am5.percent(100),
bottomWidth: 40
})
var bullet = axisDataItem.set("bullet", am5xy.AxisBullet.new(root, {
sprite: clockHand
}));
xAxis.createAxisRange(axisDataItem);
var label = chart.radarContainer.children.push(am5.Label.new(root, {
fill: am5.color(0xffffff),
centerX: am5.percent(50),
textAlign: "center",
centerY: am5.percent(50),
fontSize: "3em"
}));
axisDataItem.set("value", 50);
bullet.get("sprite").on("rotation", function () {
var value = axisDataItem.get("value");
var text = Math.round(axisDataItem.get("value")).toString();
var fill = am5.color(0x000000);
xAxis.axisRanges.each(function (axisRange) {
if (value >= axisRange.get("value") && value <= axisRange.get("endValue")) {
fill = axisRange.get("axisFill").get("fill");
}
})
label.set("text", Math.round(value).toString());
clockHand.pin.animate({ key: "fill", to: fill, duration: 500, easing: am5.ease.out(am5.ease.cubic) })
clockHand.hand.animate({ key: "fill", to: fill, duration: 500, easing: am5.ease.out(am5.ease.cubic) })
});
var i = 0;
var a = setInterval(function() {
if (i === 9) {
axisDataItem.animate({
key: "value",
to: Math.round(28),
duration: 100,
easing: am5.ease.out(am5.ease.cubic)
});
}
else if (i === 25) {
clearInterval(a);
}
else {
axisDataItem.animate({
key: "value",
to: Math.round(Math.random() * 140 - 40),
duration: 2000,
easing: am5.ease.out(am5.ease.cubic)
});
i++;
}
}
, 100);
var bandsData = [{
title: "لاغری مفرط",
direction: "rtl",
position: "right",
orientation: "rtl",
color: "#ee1f25",
lowScore: -40,
highScore: -20
}, {
title: 'لاغر',
color: "#f04922",
lowScore: -20,
highScore: 0
}, {
title: "نرمال",
color: "#fdae19",
lowScore: 0,
highScore: 20
}, {
title: "اضافه وزن",
color: "#f3eb0c",
lowScore: 20,
highScore: 40
}, {
title: "چاق",
color: "#b0d136",
lowScore: 40,
highScore: 60
}, {
title: "چاقی زیاد",
color: "#54b947",
lowScore: 60,
highScore: 80
}, {
title: "چاقی مفرط",
color: "#0f9747",
lowScore: 80,
highScore: 100
}];
am5.array.each(bandsData, function (data) {
var axisRange = xAxis.createAxisRange(xAxis.makeDataItem({}));
axisRange.setAll({
value: data.lowScore,
endValue: data.highScore
});
axisRange.get("axisFill").setAll({
visible: true,
fill: am5.color(data.color),
fillOpacity: 0.8
});
axisRange.get("label").setAll({
text: data.title,
inside: true,
radius: 15,
fontSize: "0.9em",
fill: root.interfaceColors.get("background")
});
});
chart.rtl = true;
chart.appear(1000, 100);
chart.rtl = true;
</script>
Final result is like this image:
amcharts5 result
I also searched about it in documentation of amcharts 5 but I couldn't find the answer.

Adding icons to bar charts made using c3js

I have made a stacked bar chart using c3 libraries and would like to add icons to each column (using c3 or d3). I went through their documentation but there doesnt seem to be any relevant functionality!
var chart = c3.generate({
data: {
columns: [
['data1', 30, 200, 100],
['data2', 130, 100, 140]
],
type: 'bar',
groups: [['data1', 'data2']]
},
});
You can import font-awesome and then (mis)use c3's label format configuration to set an icon for each series
var chart = c3.generate({
data: {
columns: [
['data1', 30, -200, -100, 400, 150, 250],
['data2', -50, 150, -150, 150, -50, -150],
['data3', -100, 100, -40, 100, -150, -50]
],
groups: [
['data1', 'data2']
],
type: 'bar',
labels: {
// format: function (v, id, i, j) { return "Default Format"; },
format: {
data1: function (v, id, i, j) { return "\uf1ec"; }, // a calculator
data2: function (v, id, i, j) { return "\uf212"; }, // a book
data3: function (v, id, i, j) { return "\uf1ae"; }, // a human
}
}
},
grid: {
y: {
lines: [{value: 0}]
}
}
});
You'll need this css rule -->
.c3-chart-text .c3-text {
font-family: 'FontAwesome';
}
And to import the FontAwesome css to get access to the glyphs (this may be an old version) -->
https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css
The glyph codes can be found here -->
https://fontawesome.com/cheatsheet
Example:
https://jsfiddle.net/h0g1fwpa/19/

Set the y axis spacing in c3

I have the following chart and I want to make the y axis spacing integers only (when the data to display is low, I get decimals: 0.1, 0.2...). Anyone can help?
var Presence = c3.generate({
bindto: '#presence',
data: {
url: 'ranking.csv',
x:'AC_YEAR',
types: {
Number_students: "bar",
Ranking: 'spline'
},
axes:{
Number_students: "y",
Ranking: "y2"
}
},
axis: {
y: {
label: {
text:"Students",
position: "outer-middle"
},
tick: {
outer: false}
},
y2: {
inverted:true,
show: true,
label: {
text:"Ranking position",
position: "outer-middle"
},
tick: {
outer: false
}
},
x: {
label: {
text:"Year",
position: "outer-center"
},
tick: {outer: false}
}
},
size: {
height: 400,
width: 800
},
});
The csv file looks like this:
AC_YEAR,Number_students,Ranking
2011,1,103
2012,2,30
2014,1,178
2015,1,188
But the csv is changing over time and sometimes the Number of students is 100. So that is why I do not want to fix values on the y axis, only avoid having floats when the Number of students is low (1 or 2)
Thanks in advance!
Set the y tick formatting function to return blanks on non-whole numbers
y: {
label: {
text:"Students",
position: "outer-middle"
},
tick: {
format: function (d) {
return Math.abs(Math.round(d) - d) < 0.001 ? d : "";
},
outer: false
}
},

Aligning C3 line shapes with Bar charts

We have the following mixed line chart / bar chart in C3:
a bar chart with two groups (light/dark blue is one group, gray is the
other group)
two other data sets represented as line with stroke-width = 0 that represent the limit for group1 and group2.
How can we place the circle shape for line1 aligned with the bar for group1 and the circle shape for line2 aligned with the two bars of group2?
In the following example, we basically would want one of the two circles to be moved slightly to the right so to align with the center of a group and the other one slightly to the left.
var chartSettings = {
padding: {
left: 120,
right: 120
},
bindto: '#chart',
data: {
x: 'Dates',
type: 'bar',
types: {
line1: 'line',
line2: 'line'
},
groups: [
['data2', 'data3'],
],
colors: {
data1: '#f3e274',
data2: '#85bdde',
data3: '#ccebfb'
},
},
bar: {
width: {
ratio: 0.50
}
},
point: {
r: 8
},
axis: {
x: {
type: 'timeseries',
tick: {
format: '%d-%m-%Y'
}
},
y: {
label: { // ADD
text: '',
position: 'outer-middle'
},
},
}
};
var date1 = new Date(2015, 1, 1, 0,0, 0,0);
var date2 = new Date(2015, 3, 1, 0,0, 0,0);
var date3 = new Date(2015, 6, 1, 0,0, 0,0);
var xAxis = ['Dates', date1, date2,date3];
var line1 = ['line1', 50, 60,55];
var line2 = ['line2', 70, 75,60];
var data1 = ['data1', 40, 35,30];
var data2 = ['data2', 5, 10,10];
var data3 = ['data3', 20, 15,30];
chartSettings.data.columns = [xAxis,
line1,
line2,
data1,
data2,
data3];
c3.generate(chartSettings);
#cr-chart .c3-line-accordatoTotale {
stroke-width: 0px;
}
<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"/>
var chartSettings = {
bindto: '#chart',
data: {
x: 'Dates',
type: 'bar',
types: {
line1: 'line',
line2: 'line'
},
groups: [
['data2', 'data3'],
],
names: {
line1: 'Limit for data1',
line2: 'Limit for data2 + data3',
data1: 'Data1',
data2: 'Data2',
data3: 'Data3'
},
},
bar: {
width: {
ratio: 0.50 // this makes bar width 50% of length between ticks
}
},
point: {
r: 8
},
axis: {
x: {
type: 'timeseries',
tick: {
format: '%d-%m-%Y'
}
},
y: {
label: { // ADD
text: '',
position: 'outer-middle'
}
},
}
};
var date1 = new Date(2016, 1, 1, 0, 0, 0, 0);
var date2 = new Date(2016, 3, 1, 0, 0, 0, 0);
var date3 = new Date(2016, 6, 1, 0, 0, 0, 0);
var xAxis = ['Dates',date1,date2,date3];
var line1 = ['line1', 50, 70,80];
var data1 = ['data1', 30, 40, 60];
var line2 = ['line2', 70, 60,40];
var data2 = ['data2',10,15,20];
var data3 = ['data3',15,30,5];
chartSettings.data.columns = [xAxis,
line1,
line2,
data1,
data2,
data3];
c3.generate(chartSettings);
#chart .c3-line-line1 {
stroke-width: 0px;
}
#chart .c3-line-line2 {
stroke-width: 0px;
}
<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"/>
It would be nice if you attached some jsfiddle.
But at this point I can say that you probably need to look inside .c3-chart-lines container and find desired line eighter by order:
.c3-chart-line:first-child // or last-child?
or by data name:
.c3-chart-line.c3-target-YOUR-ORANGE-DATA-NAME
Hope this helps.

c3js - Grid lines showing on top of content

I've been trying to make the x-axis grid lines to be behind the content of a c3js bar chart.
I toyed with z-index which didn't work. I tried with opacity which didn't work either.
Here is the JSFiddle with the code I was using.
https://jsfiddle.net/chaitanya81/rvhb0fy4/1/
var chart = c3.generate({
bindto: '#chart',
data: {
x : 'x',
columns: [
['x', 'M','T','W','TH','F','SA','SU'],
['revenue', 200, 300, 200, 400, 500, 700, 600.56]
],
type: 'bar'
},
color: {
pattern: ["#ff9900"]
},
axis: {
x: {
type: 'category', // this needed to load string x value
tick: {
outer: false
}
},
y: {
tick: {
outer: false
}
}
},
grid: {
x: {
lines: [
{value: "M"},
{value: "T"},
{value: "W"},
{value: "TH"},
{value: "F"},
{value: "SA"},
{value: "SU"}
]
}
},
bar: {
width: {
ratio: 0.4
}
},
legend: {
hide: true
},
tooltip: {
contents: function (data, defaultTitleFormat, defaultValueFormat, color) {
var $$ = this, config = $$.config,
titleFormat = config.tooltip_format_title || defaultTitleFormat,
nameFormat = config.tooltip_format_name || function (name) { return name; },
valueFormat = config.tooltip_format_value || defaultValueFormat,
text, i, title, value;
for (i = 0; i < data.length; i++) {
if (! (data[i] && (data[i].value || data[i].value === 0))) { continue; }
if (! text) {
title = titleFormat ? titleFormat(data[i].x) : data[i].x;
text = "<div id='tooltip' class='d3-tip'>";
}
value = valueFormat(data[i].value, data[i].ratio, data[i].id, data[i].index);
text += "<span class='value'>$" + value + "</span>";
text += "</div>";
}
return text;
}
},
transition: {
duration: 1000
}
});
Any one tried this with c3js charts?
Thanks in Advance.
You can set grid.lines.front to false
var chart = c3.generate({
bindto: '#chart',
data: {
...
},
grid: {
lines: {
front: false
}
}
});
https://jsfiddle.net/Yosephsol/bwu70xgq/
The grid line layer comes over the chart elements (bars) layer, and SVG the z-index is set by the order of the elements in the document.
You could use your regions to give the same effect. One way is
CSS
.border {
stroke: #000;
fill: transparent;
}
.whiteborder {
stroke: white;
fill: transparent;
}
Script
regions: [
{ axis: 'x', start: -0.5, end: 0, class: 'border' },
{ axis: 'x', start: -0.5, end: 1, class: 'border' },
{ axis: 'x', start: -0.5, end: 2, class: 'border' },
{ axis: 'x', start: -0.5, end: 3, class: 'border' },
{ axis: 'x', start: -0.5, end: 4, class: 'border' },
{ axis: 'x', start: -0.5, end: 5, class: 'border' },
{ axis: 'x', start: -0.5, end: 6, class: 'border' },
{ axis: 'x', start: -0.5, end: 6.5, class: 'whiteborder' },
],
The last line is to get rid of the top border (you can't style different borders of a rect differently - there's an alternative [hack] using stroke-dasharray, but it depends on the relative height and width of your regions)
Fiddle - https://jsfiddle.net/d611yq7x/

Resources