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.
Related
I am following this tutorial https://bytutorial.com/blogs/open-source-chart/learn-how-to-create-multiple-bar-charts-with-multiple-line-charts-in-nvd3 which is great .
Even though, it has a colorfull way to display the key values. Instead of the name of the key, shows a div with the background color of the key:
<div class='tooltip'>
<span>Legend:</span>
<div style='background:" + key.series[0].color + ";display:inline-block;height:150px;width:150px;'> </div>
</div>
How can I show the name of the key?, instead of its color.
This is my graph: http://codepen.io/neonpulp/pen/zBZgrv . Below is the full code also.
function buildGraph(){
//this will hold of our main data consists of multiple chart data
var data = [];
//variables to hold monthly month
var monthList = ['Ene 2016','Feb 2016','Mar 2016','Apr 2016','May 2014','Jun 2016','Jul 2016','Aug 2016', 'Sep 2016', 'Oct 2016', 'Nov 2016', 'Dec 2016'];
var monthlyIncome = [0, 2757820, 3447270, 0, 0, 0, 0, 0, 0, 0, 0, 0];
var companiesNumber = [0, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0];
//Array to hold each individual coordinate x and y values
var monthlyIncomeValues = [];
var companiesNumberValues = [];
//Looping the data and fetch into array
for(var i = 0; i < monthList.length; i++){
var xyIncome = {x: i, y: monthlyIncome[i]};
monthlyIncomeValues.push(xyIncome);
var xyCompanies = {x: i, y: companiesNumber[i]};
companiesNumberValues.push(xyCompanies);
}
//bar chart
var dataIncome = { key: "Monthly Income", values: monthlyIncomeValues, type: "bar", yAxis: 2, color: '#00913B' }
//line chart
var dataCompanies = { key: "Amount of companies", values: companiesNumberValues, type: "line", yAxis: 1, color: '#00C3D9' }
//Insert the values array into data variable
data.push(dataIncome);
data.push(dataCompanies);
//build the graph
nv.addGraph(function () {
//build as multichart graphs and set the margin right and left to 100px.
var chart = nv.models.multiChart()
.margin({left: 100, right: 100})
//customize the tool tip
chart.tooltip.contentGenerator(function (key, x, y, e, graph) {
return "<div class='tooltip'><span>Month:</span> " + monthList[key.index] + "</div>" + "<div class='tooltip'><span>Value:</span> " + key.series[0].value + "</div><div class='tooltip'><span>Legend:</span> <div style='background:" + key.series[0].color + ";display:inline-block;height:15px;width:15px;'> </div></div>";
});
//Overwrite the x axis label and replace it with the month name
chart.xAxis.tickFormat(function (d) { return monthList[d] });
//Chart Interpolate
chart.interpolate("linear")
//Dollar Sign
chart.yAxis2.tickFormat(function(d) { return '$' + d3.format(',f')(d) });
//get the chart svg object and fecth the data to build the chart
d3.select('#chart svg')
.datum(data)
.transition().duration(500).call(chart);
return chart;
});
}
//call the function to build the graph.
buildGraph();
I'm trying to create a "linePlusBar" chart with NVD3 . The x-axis values are the months of the year:
var monthList = ['Ene 2016','Feb 2016','Mar 2016','Apr 2016','May 2014','Jun 2016','Jul 2016','Aug 2016', 'Sep 2016', 'Oct 2016', 'Nov 2016', 'Dec 2016'];
For some reason only the bar graph shows this value in the tooltip, for instance Month:Aug 2016.
The line graph instead shows this value in the tooltip as "Month: undefined".
What could be the problem?
This is my graph: http://codepen.io/neonpulp/pen/zBZgrv . Below is the code also.
function buildGraph(){
//this will hold of our main data consists of multiple chart data
var data = [];
//variables to hold monthly month
var monthList = ['Ene 2016','Feb 2016','Mar 2016','Apr 2016','May 2014','Jun 2016','Jul 2016','Aug 2016', 'Sep 2016', 'Oct 2016', 'Nov 2016', 'Dec 2016'];
var monthlyIncome = [0, 2757820, 3447270, 0, 0, 0, 0, 0, 0, 0, 0, 0];
var companiesNumber = [0, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0];
//Array to hold each individual coordinate x and y values
var monthlyIncomeValues = [];
var companiesNumberValues = [];
//Looping the data and fetch into array
for(var i = 0; i < monthList.length; i++){
var xyIncome = {x: i, y: monthlyIncome[i]};
monthlyIncomeValues.push(xyIncome);
var xyCompanies = {x: i, y: companiesNumber[i]};
companiesNumberValues.push(xyCompanies);
}
//bar chart
var dataIncome = { key: "Monthly Income", values: monthlyIncomeValues, type: "bar", yAxis: 2, color: '#00913B' }
//line chart
var dataCompanies = { key: "Amount of companies", values: companiesNumberValues, type: "line", yAxis: 1, color: '#00C3D9' }
//Insert the values array into data variable
data.push(dataIncome);
data.push(dataCompanies);
//build the graph
nv.addGraph(function () {
//build as multichart graphs and set the margin right and left to 100px.
var chart = nv.models.multiChart()
.margin({left: 100, right: 100})
//customize the tool tip
chart.tooltip.contentGenerator(function (key, x, y, e, graph) {
return "<div class='tooltip'><span>Month:</span> " + monthList[key.index] + "</div>" + "<div class='tooltip'><span>Value:</span> " + key.series[0].value + "</div><div class='tooltip'><span>Legend:</span> <div style='background:" + key.series[0].color + ";display:inline-block;height:15px;width:15px;'> </div></div>";
});
//Overwrite the x axis label and replace it with the month name
chart.xAxis.tickFormat(function (d) { return monthList[d] });
//Chart Interpolate
chart.interpolate("linear")
//Dollar Sign
chart.yAxis2.tickFormat(function(d) { return '$' + d3.format(',f')(d) });
//get the chart svg object and fecth the data to build the chart
d3.select('#chart svg')
.datum(data)
.transition().duration(500).call(chart);
return chart;
});
}
//call the function to build the graph.
buildGraph();
The reason is that key for line chart doesn't include index - it has pointIndex instead.
Try this:
monthList[key.index || key.pointIndex]
Demo: http://codepen.io/LukaszWiktor/pen/xOdKmQ
I am making a stacked multi chart bar graph like this one
http://nvd3.org/examples/multiBar.html
Till now I am able to push my values on Y- axis and X axis too but the problem I am facing is that the all the values are not getting displayed on the x axis but only 10 values are getting displayed . I am using nvD3 library in my angular code . and displaying date on x axis.
$scope.options1 = {
chart: {
type: 'multiBarChart',
height: 600,
margin: {
top: 20,
right: 20,
bottom: 200,
left: 45
},
clipEdge: false,
duration: 500,
stacked: true,
groupSpacing: 0.1,
useInteractiveGuideline: true,
showMaxMin: false,
xAxis: {
axisLabel: 'Timeline',
showMaxMin: false,
tickFormat: function(d) {
return d3.time.format('%d-%m-%y')(new Date(d))
},
xScale:d3.time.scale(),
rotateLabels: '-70'
},
yAxis: {
axisLabel: 'Pending Bills',
axisLabelDistance: -20,
groupSpacing: 0.1,
tickFormat: function(d) {
return d3.format(',f')(d);
}
}
}
};
generating ticking value array using this function
$scope.options1.chart.xAxis.tickValues = function() {
var xTick = _.map(data.data.data[0].values, function(value) {
return value.x;
});
xTick = _.sortBy(xTick, function(date){ return new Date(date); });
console.log(xTick);
return xTick;
}
the output of the console.log(xTick) is something like this which is all dates -
["2015-09-01", "2015-09-02", "2015-09-03", "2015-09-04", "2015-09-05",
"2015-09-06", "2015-09-07", "2015-09-08", "2015-09-09", "2015-09-10",
"2015-09-11", "2015-09-12", "2015-09-13", "2015-09-14", "2015-09-15",
"2015-09-16", "2015-09-17", "2015-09-18", "2015-09-19", "2015-09-20",
"2015-09-21", "2015-09-22", "2015-09-23", "2015-09-24", "2015-09-25",
"2015-09-26", "2015-09-27", "2015-09-28", "2015-09-29", "2015-09-30",
"2015-10-01", "2015-10-02", "2015-10-03", "2015-10-04", "2015-10-05",
"2015-10-06", "2015-10-07", "2015-10-08", "2015-10-09", "2015-10-10",
"2015-10-11", "2015-10-12", "2015-10-13", "2015-10-14", "2015-10-15",
"2015-10-16", "2015-10-17", "2015-10-18", "2015-10-19", "2015-10-20"]
as much I read about the it. all the dates should be get plotted on x axis but they are not
If you want to display all the ticks on X-Axis, you can add this option to your chart options :
"reduceXTicks": false,
For extended option page you can visit :
Angular NVD3 - MultiBarChart
Hope it helps.
chart: {
type: 'chartType',
xAxis: {
ticks:8
}
}
You can try "ticks" property if you want to display a specific number of ticks on the axis.
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);}
I'm using nvd3, but I think this is a general d3.js question about time scale and formatting. I've created a simple example that illustrates the problem (see code below):
If I omit .tickFormat for the xAxis, it works fine without date formatting. With the example below I get the error:
Uncaught TypeError: Object 1326000000000 has no method 'getMonth'
nv.addGraph(function() {
var chart = nv.models.lineChart();
chart.xAxis
.axisLabel('Date')
.rotateLabels(-45)
.tickFormat(d3.time.format('%b %d')) ;
chart.yAxis
.axisLabel('Activity')
.tickFormat(d3.format('d'));
d3.select('#chart svg')
.datum(fakeActivityByDate())
.transition().duration(500)
.call(chart);
nv.utils.windowResize(function() { d3.select('#chart svg').call(chart) });
return chart;
});
function days(num) {
return num*60*60*1000*24
}
/**************************************
* Simple test data generator
*/
function fakeActivityByDate() {
var lineData = [];
var y = 0;
var start_date = new Date() - days(365); // One year ago
for (var i = 0; i < 100; i++) {
lineData.push({x: new Date(start_date + days(i)), y: y});
y = y + Math.floor((Math.random()*10) - 3);
}
return [
{
values: lineData,
key: 'Activity',
color: '#ff7f0e'
}
];
}
The example (now fixed) is in nvd3 with date axis.
Try creating a new Date object before the tick for the x-axis gets passed to the formatter:
.tickFormat(function(d) { return d3.time.format('%b %d')(new Date(d)); })
See the documentation for d3.time.format to see how you can customize the formatting string.
Adding on to seliopou's answer, to correctly align the dates with the x-axis, try this:
chart.xAxis
.tickFormat(function(d) {
return d3.time.format('%d-%m-%y')(new Date(d))
});
chart.xScale(d3.time.scale()); //fixes misalignment of timescale with line graph