I am trying to display a real-time line-graph using angular.js nvd3 [1]. It should plot altitude vs. time.
The problem I am having is with getting the x-axis to show the time data array correctly. This is what it looks like:
http://i.imgur.com/PQeskpf.png
and this is the data that I am trying to show:
$scope.chart1data = [
{
"key": "Altitude",
"values": [{x:"2013-03-04_12:00:00",y:50},{x:'2013-03-04_13:00:00',y:1000}]
}
];
chart options:
$scope.chart1options = {
chart: {
type: 'lineChart',
height: 350,
x: function(d){ return d.x; },
y: function(d){ return d.y; },
useInteractiveGuideline: true,
dispatch: {
stateChange: function(e){ console.log("stateChange"); },
changeState: function(e){ console.log("changeState"); },
tooltipShow: function(e){ console.log("tooltipShow"); },
tooltipHide: function(e){ console.log("tooltipHide"); }
},
xAxis: {
axisLabel: 'Time',
tickformat: function(d) {
return d3.time.format('%Y-%m-%d_%H:%M:%S')(new Date(d))
}
},
yAxis: {
axisLabel: 'Altitude (m)',
tickFormat: function(d){
return d3.format('.02f')(d);
},
axisLabelDistance: 100
}
}
};
If anyone knows how to get the x axis to show month/date-hour:minute for each data point, and have it scaled by time I could really use some help!
[1] http://krispo.github.io/angular-nvd3/#/quickstart
Related
I have a graph who can have one set of data or multiples set of data. I need to check every stateChange and triggered the callback (he make actions that I need to make at every changes).
here is my graph :
scope.options = {
chart: {
type: 'lineChart',
height: 450,
margin : {
top: 20,
right: 20,
bottom: 40,
left: 55
},
useInteractiveGuideline: false,
dispatch: {
stateChange: function(){ console.log("stateChange"); },
changeState: function(){ console.log("changeState"); },
tooltipShow: function(){ console.log("tooltipShow"); },
tooltipHide: function(){ console.log("tooltipHide"); },
},
xAxis: {
axisLabel: 'Temperature (Celcius)'
},
yAxis: {
axisLabel: 'Fluorescence',
tickFormat: function(d){
return d3.format('0f')(d);
},
axisLabelDistance: -10
},
callback: function(chart){
console.log("!!! lineChart callback !!!");
// If there is a tm point we show it
if (data.length === 1 && angular.isObject(tmPoints[data[0].key])){
console.log("SHOW TM");
data[0].values.forEach(function(element){
if (parseInt(element.x) === parseInt(tmPoints[data[0].key].tm)){
// Recuperer l'objet point et non ses valeurs
highlightPoint(chart, {'point' : element}, 10, true);
}
});
}
console.log(data.length);
if (data.length === 1) {
chart.lines.dispatch.on("elementClick", function(e) {
// Faire ça uniquement si il y a UN graph
if (clickedPoints.length >= 2){
// Remove the first point of the array
var pointToDelete = clickedPoints.shift(0,1);
// And remove his highlight
removeHighlightPoint(pointToDelete, pointToDelete.element.attributes[1].nodeValue);
}
clickedPoints.push(e);
highlightPoint(chart, e, 7, false);
});
}
},
},
title: {
enable: true,
text: 'Title for Line Chart'
},
};
I need to make actions when only one set of data is show, I have my condition for the if but the callback is called only one time at the beggining, how can I call at every stateChange ?
I also need to call the callback when my options change, currently when I change the scope.options, no one of the event (stateChange) are triggered, and the callback is not triggered too.
Anyone have an idea ?
I am writing to ask you why the Y Axis starts from -1.0 when all the values are equal to zero despite I have set the option forceY to 0. How I can solve this problem.
Please find attached the plunker: example
var app = angular.module('plunker', ['nvd3']);
app.controller('MainCtrl', function($scope) {
$scope.options = {
chart: {
type: 'multiBarChart',
height: 450,
forceY:[0],
margin : {
top: 20,
right: 20,
bottom: 45,
left: 45
},
clipEdge: true,
duration: 500,
stacked: true,
xAxis: {
axisLabel: 'Time (ms)',
showMaxMin: false,
tickFormat: function(d){
return d3.format(',f')(d);
}
,ordered:'bottom'
},
yAxis: {
axisLabel: 'Y Axis',
axisLabelDistance: -20,
tickFormat: function(d){
return d3.format(',.1f')(d);
}
}
}
};
$scope.data = [{"key":"2016","values":[{"x":"Gennaio","y":0,"color":"blue"},{"x":"Febbraio","y":0,"color":"#FFFFFF"},{"x":"Marzo","y":0,"color":"#FFFFFF"},{"x":"Aprile","y":0,"color":"#FFFFFF"},{"x":"Maggio","y":0,"color":"#FFFFFF"},{"x":"Giugno","y":0,"color":"#FFFFFF"},{"x":"Luglio","y":0,"color":"#FFFFFF"},{"x":"Agosto","y":0,"color":"#FFFFFF"},{"x":"Settembre","y":0,"color":"#FFFFFF"},{"x":"Ottobre","y":0,"color":"#FFFFFF"},{"x":"Novembre","y":0,"color":"#FFFFFF"},{"x":"Dicembre","y":0,"color":"#FFFFFF"}]},{"key":"2017","values":[{"x":"Gennaio","y":0,"color":"#FF9896"},{"x":"Febbraio","y":0,"color":"#FF9896"},{"x":"Marzo","y":0,"color":"#FF9896"},{"x":"Aprile","y":0,"color":"#FF9896"},{"x":"Maggio","y":0,"color":"#FF9896"},{"x":"Giugno","y":0,"color":"#FF9896"},{"x":"Luglio","y":0,"color":"#FF9896"},{"x":"Agosto","y":0,"color":"#FF9896"},{"x":"Settembre","y":0,"color":"#FF9896"},{"x":"Ottobre","y":0,"color":"#FF9896"},{"x":"Novembre","y":0,"color":"#FF9896"},{"x":"Dicembre","y":0,"color":"#FF9896"}]}];
});
Maybe it's a bug of the nvd3 angularjs library (https://krispo.github.io/angular-nvd3/).
You try to set the property forceY to 1 value.
The key here is yDomain1:[0,100]
chart: {
type: 'multiChart',
height: 600,
margin: {
top: 0,
right: 20,
bottom: 120,
left: 45
},
x: function (d) {
if (d) {
return d.x;
}
},
y: function (d) {
if (d) {
return d.y;
}
},
clipEdge: true,
showControls: false,
bars1: {
},
lines1: {
interactive: false,
},
staggerLabels: false,
transitionDuration: 1000,
stacked: false,
reduceXTicks: false,
xAxis: {
ticks: 11,
showMaxMin: false,
rotateLabels: 70,
tickFormat: function (d) {
if (d) {
var serializedString = d.toString();
var monthString = moment().month(Number(serializedString.substring(4)) - 1).format("MMM");
var yearString = serializedString.substring(0, 4);
return monthString + ", " + yearString;
}
},
},
yDomain1: [-10, 100],
yAxis1: {
axisLabel: '% Values',
axisLabelDistance: 100,
}
}
}
I create an nvd3 graph with the angular-nvd3 directive:
<nvd3 id="analytics-community" options="vm.community.options" data="vm.community.data" config="vm.graphConfig" class="with-3d-shadow with-transitions"></nvd3>
However it does not seem possible to filter the data attribute using |filter:something as it ends up looping infinitely and angular breaks with infinite loop error.
Graph options are setup with:
vm.graphOptions = {
chart: {
type: 'lineChart',
height: 300,
margin : {
top: 50,
right: 50,
bottom: 50,
left: 50
},
x: function(d) {
return d3.time.format.iso.parse(d.key);
},
y: function(d) {
return d.value;
},
useInteractiveGuideline: false,
dispatch: {
stateChange: function(e) { },
changeState: function(e) { },
tooltipShow: function(e) { },
tooltipHide: function(e) { }
},
xScale: d3.time.scale(),
xAxis: {
axisLabel: 'Date',
tickFormat: function (d) {
return d3.time.format('%b %Y')(new Date(d));
}
},
yAxis: {
axisLabel: 'Count',
tickFormat: function(d) {
return d;
}
}
}
};
And the data is set-up with:
vm.community.data = [
{
key: 'Members',
values: vm.statsModel.registeredMembers
},
{
key: 'Students',
values: vm.statsModel.registeredStudents
},
{
key: 'Alumni',
values: vm.statsModel.registeredAlumni
}
];
Where vm.statsModel.registeredMembers is like:
[
{
key: "2015-06-15",
value: 458
},
{
key: "2015-06-23",
value: 459
},
{
key: "2015-06-27",
value: 460
}
]
Any ideas?
Setting the xDomain in vm.graphOptions.chart worked:
vm.graphOptions.chart.xDomain = [new Date(vm.selectedItem.date), dateToday]
Where vm.selectedItem.date = new Date().setMonth(new Date().getMonth() - 6) for 6 months ago... and dateToday = new Date()
So I just $watch for changes on vm.selectedItem which changes with a select box and update xDomain.
Can anyone tell me how to specify a color or css class for the y axis of an angular-nvd3 lineChart ?
I've been specifying the options:
<nvd3 options="lineChartOptions" data="graphData" ></nvd3>
and then have all the options in an object:
$scope.lineChartOptions = {
chart: {
type: 'lineChart',
showLegend:false,
forceY:[0,5], // make y axis start at 0 to 5
forceX:[1,4],
// interpolate:"monotone",
height: 400,
width: 600,
margin : {
top: 20,
right: 20,
bottom: 40,
left: 55
},
x: function(d){ return d.x; },
y: function(d){ return d.y; },
useInteractiveGuideline: true,
tooltip: {
contentGenerator: function(d) { return '<h3>HELLO WORLD</h3>'; }
},
dispatch: {
stateChange: function(e){ console.log("stateChange"); },
changeState: function(e){ console.log("changeState"); },
tooltipShow: function(e){ console.log("tooltipShow"); },
tooltipHide: function(e){ console.log("tooltipHide"); }
},
xAxis: {
// axisLabel: 'Week',
ticks: 4, // make x-axis show all 4 weeks,
// tickFormat: function(d){
// return "week " + d;
// }
},
showYAxis: true,
yAxis: {
// axisLabel: 'Score',
// tickFormat: function(d){
// return d3.format('.02f')(d);
// },
ticks: 6,
axisLabelDistance: -10
},
callback: function(chart){
//console.log("!!! lineChart callback !!!");
}
},
// title: {
// enable: true,
// text: 'Title for Line Chart'
// },
// subtitle: {
// enable: true,
// text: 'Subtitle for simple line chart... ',
// css: {
// 'text-align': 'center',
// 'margin': '10px 13px 0px 7px'
// }
// },
// caption: {
// enable: true,
// html: '<b>AND</b> we can put any sort of html here too...',
// css: {
// 'text-align': 'justify',
// 'margin': '10px 13px 0px 7px'
// }
// }
};
But cannot figure out for the life of me how to specify a color for the axes or how to specify a css class for the tick texts...
Any help would be greatly appreciated...
For the y axis you can do it by css, as follows:
.nvd3 .nv-axis path { fill: #E5E5E5; stroke: #E5E5E5; }
I am trying to modify the linewithFocusChart's focus properties (the focus being the small navigable viewport beneath the main chart) using the focus options (focusEnable, focusHeight, etc). These options are not having any affect on my graph though. I am using Angular-nvD3 directives. Any ideas?
HTML
<nvd3 options="options" data="data" config="config"></nvd3>
Angular controller
$scope.options = {
chart: {
type: 'lineWithFocusChart',
height: 350,
margin : {
"top": 20,
"right": 40,
"bottom": 60,
"left": 40
},
focusEnable:true,
focusHeight: 80,
focusShowAxisX: true,
focusShowAxisY: false,
brushExtent: [new Date(1427846400000), new Date(1435708800000)],
xAxis: {
axisLabel: '',
tickFormat: function(d){
return d3.time.format('%b-%Y')(
new Date(d))
}
},
x2Axis: {
tickFormat: function(d){
return d3.time.format('%b/%Y')(
new Date(d))
}
},
yAxis: {
axisLabel: '',
tickFormat: function(d){
return d3.format(',d')(d);
},
rotateYLabel: false
},
y2Axis: {
tickFormat: function(d){
return d3.format(',')(d);
}
},
tooltip: {
distance: 0,
duration: 100,
hideDelay: 100
},
tooltipContent: function (key, x, y, e) {
return '<h3>' + e.point.y + '</h3>' +
'<p>' + x + '</p>';
}
}
};
From a quick look at the source code, the option you are looking for is focusHeight.
{
"chart": {
"type": "linePlusBarChart",
"height": 500,
"margin": {
"top": 30,
"right": 75,
"bottom": 50,
"left": 75
},
"bars": {
"forceY": [
0
]
},
"bars2": {
"forceY": [
0
]
},
"color": [
"#2ca02c",
"darkred"
],
"xAxis": {
"axisLabel": "X Axis"
},
"x2Axis": {
"showMaxMin": false
},
"y1Axis": {
"axisLabel": "Y1 Axis"
},
"y2Axis": {
"axisLabel": "Y2 Axis"
},
"y3Axis": {},
"y4Axis": {},
"transitionDuration": 250,
"focusHeight": 300 //<-- ADD THIS
}
}
The reason the options did not work for me was because I was using an outdated version of angular-nvd3 directive -- one in which the aforementioned options were not supported. I uninstalled angular-directive, nvd3, and d3 with bower, and updated to angular-directive v1.0.0-rc2, nvd3 v1.8.1 by running the following command:
bower install angular-nvd3#1.0.0-rc.2 --save
Problem resolved!