How to fill the area between two lines using C3 chart? - c3.js

Please open this link: http://c3js.org/samples/timeseries.html
Replace the code of textarea by following code:
var chart = c3.generate({
data: {
x: 'x',
columns: [
['x', '2013-01-01', '2013-01-02', '2013-01-03', '2013-01-04',],
['bottomline', null,30, 150, 250],
['topline', 130, 340, 350,null]
]
},
axis: {
x: {
type: 'timeseries',
tick: {
format: '%Y-%m-%d'
}
}
}
});
You will be able to see a graph like Fig:1 below.
Now I want to fill the area between two lines shown in the graph with some color. I want to make it like Fig:2 below.
Fig:1 and then Fig:2
Please help me on this.
Thanks in advance.

This is an old question, but just in case someone also meets this problem. Here is a working fiddle for filling between two lines.
Fill between two lines
Note: the null points should be handled before feeding to charts since null will be mapped to 0 automatically from C3 point of view.
Code snippet:
function fillArea(){
var indexies = d3.range( items.length );
var yscale = chart.internal.y;
var xscale = chart.internal.x;
var area = d3.svg.area()
.interpolate("linear")
.x(function(d) { return xscale(new Date(items[d].x)); })
.y0(function(d) { return yscale(items[d].bottomline); })
.y1(function(d) { return yscale(items[d].topline); });
d3.select("#mychart svg g").append('path')
.datum(indexies)
.attr('class', 'area')
.attr('d', area);}

Related

Custom legend based on color of bars in a dc.js composite chart

I implemented a composite chart with two bar charts in which one bar chart consists of bars with different colored bars.
Now, I want to create a custom legend that represents each color bar (similar to https://dc-js.github.io/dc.js/examples/pie-external-labels.html used for pie chart).
Below is the code snippet of what I've done so far:
var buttonPress = dc.barChart(composite)
.dimension(joyTimeDimension)
//.renderlet(colorRenderlet)
//.colors('red')
.colors(colorbrewer.Set1[5])
.colorDomain([101, 105])
.colorAccessor(function (d) {
return d.value;
})
.group(btnGroup, "Button Press")
.keyAccessor(function(d) {return d.key[0];})
.valueAccessor(function (d) {
return d.value;
})
.title( function(d){
return [
"Time: "+d.key[0],
"button Name: "+d.key[1],
"button: "+ d.value
].join('\n')
});
var joyStick = dc.barChart(composite)
.dimension(joyTimeDimension)
.colors('blue')
.group(stepperGroup,"Joy Stick Movement")
.keyAccessor(function(d) {return d.key[0];})
.title( function(d){
return [
"Time: "+d.key[0],
"Stepper Position: "+ d.value
].join('\n')
});
composite
.width(1200)
.transitionDuration(500)
.margins({top: 30, right: 50, bottom: 25, left: 40})
.x(d3.time.scale().domain([startDate,currDate]))
.xUnits(function(){return 150;})
//.xUnits(d3.time.second)
.elasticY(true)
.legend(dc.legend().x(1000).y(4).itemHeight(13).gap(5))
.renderHorizontalGridLines(true)
.renderTitle(true)
.shareTitle(false)
.compose([buttonPress, joyStick])
.brushOn(false)
Is there a way to create a custom legend for this scenario?
Thanks in advance.
Let me provide a little bit of background about how the legend is built.
The legend in dc.js is really not all that sophisticated. It just calls .legendables() on the chart, and the chart decides what items to display in the legend.
Each chart has its own special-purpose code for this.
If we look at the source for compositeChart.legendables(), it's just recursively getting the legendables for each child chart and concatenating them:
_chart.legendables = function () {
return _children.reduce(function (items, child) {
if (_shareColors) {
child.colors(_chart.colors());
}
items.push.apply(items, child.legendables());
return items;
}, []);
};
The pie chart creates a legendable for each pie slice:
_chart.legendables = function () {
return _chart.data().map(function (d, i) {
var legendable = {name: d.key, data: d.value, others: d.others, chart: _chart};
legendable.color = _chart.getColor(d, i);
return legendable;
});
};
The legendables for the bar chart come from the stack mixin, which creates a legendable for each stack:
_chart.legendables = function () {
return _stack.map(function (layer, i) {
return {
chart: _chart,
name: layer.name,
hidden: layer.hidden || false,
color: _chart.getColor.call(layer, layer.values, i)
};
});
};
Given that there's currently no way to get a bar chart to display a pie chart's legend, I think the easiest thing to do is override legendables for your bar chart with its custom colors:
buttonPress.legendables = function() {
return btnGroup.all().map(function(kv) {
return {
chart: buttonPress,
// display the value as the text (not sure what you want here)
name: kv.value,
// apply the chart's color scale to get the color
color: buttonPress.colors()(kv.value)
};
})
};
There are probably some more details to be worked out, such as what if the same value occurs twice? I am assuming you can just read the input data from the group and .map() it, but you might need to generate your data a different way.
But this should give the general idea. Lmk if it doesn't work and I'll be glad to follow up.

How to add a title to C3 Gauge Chart?

I am using RStudio to deal with C3 Gauge Chart. Since I am not much informed about javascript. I am having a trouble to do some small things such as adding a title.
I would like to add a title on it. However, I am having a trouble with it. Please help! Here is the code below.
output$gauge1 <- renderC3Gauge({
PTable <- Projects
if (input$accountname != "All") {
Projects <- Projects[Projects$AccountName == input$accountname,]
}
if (input$sponsorname != "All") {
Projects <- Projects[Projects$SponsorName == input$sponsorname,]
}
if (input$typename != "All") {
Projects <- Projects[Projects$TypeName == input$typename,]
}
Projects
C3Gauge(mean(Projects$PercentComplete))
})
}
shinyApp(ui=ui,server=server)
--------------------------------------------------------
HTMLWidgets.widget({
name: 'C3Gauge',
type: 'output',
factory: function(el, width, height) {
// TODO: define shared variables for this instance
return {
renderValue: function(x) {
// create a chart and set options
// note that via the c3.js API we bind the chart to the element with id equal to chart1
var chart = c3.generate({
bindto: el,
data: {
json: x,
type: 'gauge',
},
gauge: {
label:{
//returning here the value and not the ratio
format: function(value, ratio){ return value;}
},
min: 0,
max: 100,
width: 15,
units: 'value' //this is only the text for the label
}
});
},
resize: function(width, height) {
// TODO: code to re-render the widget with a new size
}
};
}
});
By deafult C3.js cannot add title to gauge chart, but you can do it with D3.js, which C3 is based on.
You have to add oninit callback into param object:
var chart = c3.generate({
oninit: function()
{
d3
.select(el)
.select("svg")
.append("text")
.attr("x", "50%" )
.attr("y", "100%")
.style("text-anchor", "middle")
.text("Your chart title goes here");
},
gauge chart title example.

dc.js multiple select menu with checkboxes

I have a dataset which consists of 5 columns -> country, id, value and sector. I was able to create a row chart in dc.js using the value and country, where country is my dimension.
var rowChart = dc.rowChart('#rowChart');
d3.csv('data.csv', function(data){
data.forEach(function(d){
d.country = d.country;
d.id = d.id;
d.value = +d.value;
d.sector = d.sector;
});
var height = 300;
var width = 300;
var ndx = crossfilter(data)
var countryDim = data.dimension(function (d) {
return d.country;
});
var countryGroup = countryDim.group().reduceSum(function (d) {
return d.value
})
rowChart
.width(300)
.height(900)
.margins({top: 10, right: 10, bottom: -1, left: 30})
.dimension(countryDim)
.group(countryGroup)
.colors('#86BC25')
.ordering(function (d) { return -d.value; })
.elasticX(true)
.xAxis();
rowChart
.title(function (d) { return d.value;})
.renderTitleLabel(true)
.titleLabelOffsetX(10);
dc.renderAll();
});
and this is my data in csv
country,id,value,sector
USA,0982,10,high
AUS,0983,9,high
IND,0982,10,high
CHN,0982,8,high
CUB,0986,5,middle
FIN,0987,low
i tried creating a jsfiddle, but does not seem to work, sorry my first time
http://jsfiddle.net/i8rice/2r76bjt7/4/
I want to be able to create two drop down with check boxes. One to filter the row chart by country and another by sector. So if I first filter the sector by 'high' in the drop down menu the row chart will get filtered and the other drop down menu should only show me the 5 'high' countries.
I know this is achievable using dc.selectMenu but I wan that drop down check box style. I was wondering if this is possible with dc.js?
Sorry I am very new to asking questions and in d3.js, dc.js and crossfilter.
Thanks to Gordon the check box within the drop down menu was working. However upon discussing with a few others, they have suggested that the check box, once ticked, is not calling the event handler, so wrote this, which is pretty much the same as the one within dc.js
selectField.on('postRender', function() {
$('#menuselect select').change(function(){
console.log($(this).val())
if ($(this).val() && $(this).val() != "") {
selectField.replaceFilter([$(this).val()]);
} else {
selectField.filterAll();
}
dc.events.trigger(function () {
dc.redrawAll();
});
}).multipleSelect({ placeholder: "Select Country"})
});
And everything worked, well, tested it on local. I don't know of any other ways as I am still new to this.

NVD3 x axis time scale misaligned

Im trying to set up a line chart nvd3 graphic, but im getting time value on x axis not vertically aligned, heres the code:
function fillData() {
var test1 = [],
test2 = [],
test3 = [];
var now = new Date(),
day = 1000*60*60*24;
var cont = 0;
for (var i = now - 9*day; i < now; i+=day)
{
var arr = [400,431,401,430,429,450,448,498,421,421];
var arr1 = [420,415,421,410,439,430,468,448,441,421];
var arr2 = [410,425,431,420,459,420,458,438,451,421];
test1.push({x: i, y: arr[cont]});
test2.push({x: i, y: arr1[cont]});
test3.push({x: i, y: arr2[cont]});
cont+=1;
} // fin for
return [
{
values: test1,
area: true,
key: 'test1',
color: '#81BA63'
},
{
values: test2,
area: true,
key: 'test2',
color: '#EAEAEA'
},
{
values: test3,
area: true,
key: 'test3',
color: '#6389BA'
}
];
}
nv.addGraph(function() {
var chart = nv.models.lineChart()
.margin({top: 0, bottom: 25, left: 45, right: 0})
.showLegend(true)
.forceY([300,500])
chart.yAxis
.showMaxMin(true)
.tickFormat(d3.format('.02'))
chart.xAxis
.showMaxMin(false)
.tickFormat(function(d) { return d3.time.format('%d - %b')(new Date(d)) });
chart.xScale(d3.time.scale());
d3.select('#sources-chart-line svg')
.datum(fillData())
.transition().duration(500)
.call(chart);
nv.utils.windowResize(chart.update);
return chart;
});
problem screenshot: http://oi57.tinypic.com/i6gq2t.jpg
Thanks in Advance!!
The problem is that the number of data points (9) and axis ticks (8) is different. D3 picks "representative" ticks for the scale, which aren't necessarily aligned with the data points. Therefore, you get ticks between data points for which the date is still correct, but not at exactly midnight like the data points.
One way of fixing this is to explicitly specify the tick values:
var data = fillData();
chart.xAxis
.tickValues(data[0].values.map(function(d) { return d.x; }));
This is a bit ugly, but it shows the principle and you can refactor the code to make these values better accessible.

how to disable the x axis and y axis line in google api line chart

im using google api for line graph in my web application. in that line chart i dont want x axis line and y axis line, but i cant to fine how to remove the lines except the graph. could you please help me. i used this example for my practice
<script type="text/javascript">
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Year', 'Sales', 'Expenses'],
['2004', 1000, 400],
['2005', 1170, 460],
['2006', 660, 1120],
['2007', 1030, 540]
]);
var options = {
title: 'Company Performance'
};
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
</script>
you cant remove or disable your x and y axis in google api the alter way is to set the baselineColor and gridlineColor same as the background color and set the textPosition to none.
vAxis:{
baselineColor: '#fff',
gridlineColor: '#fff',
textPosition: 'none'
}
With the current version of Google Charts, the following removes axis lines:
hAxis: {
baselineColor: 'none',
ticks: []
},
vAxis: {
baselineColor: 'none',
ticks: []
}

Resources