Reputation: 339
I am new with d3 and json. I am trying to construct a horizontal gantt chart. Earlier I have acieved the same using inline arrays which i stored in var dataset. But now I have replaced the arrays with json object array .
[ {
"process" :"process-name 1",
"stage" : "stage name 1",
"activities": [
{
"activity_name": "waiting",
"start": new Date('2012-12-10T06:45+05:30'),
"end": new Date('2012-10-10T08:45+05:30'),
},
{
"activity_name": "processing",
"start": new Date('2012-10-11T05:45+05:30'),
"end": new Date('2012-10-11T06:45+05:30'),
},
{
"activity_name": "pending",
"start": new Date('2012-10-12T11:45+05:30'),
"end": new Date('2012-10-13T12:45+05:30'),
}
]
},
{
"process" :"process-name 2",
"stage" : "stage name 2",
"activities": [
{
"activity_name": "waiting",
"start": new Date('2012-10-22T06:45+05:30'),
"end": new Date('2012-10-23T08:45+05:30'),
},
{
"activity_name": "processing",
"start": new Date('2012-10-25T05:45+05:30'),
"end": new Date('2012-10-25T06:45+05:30'),
},
{
"activity_name": "pending",
"start": new Date('2012-10-27T11:45+05:30'),
"end": new Date('2012-10-27T12:45+05:30'),
}
]
}
];
The d3 part of the code to draw the rectangle is this :
console.log(dataset);
var height = 600;
var width = 500;
var x = d3.time.scale().domain([new Date(2011, 0, 1,23,33,00), new Date(2013, 0, 1, 23, 59)]).range([0, width]);
var svg = d3.selectAll("body")
.append("svg")
.attr("width",width)
.attr("height",height)
.attr("shape-rendering","crispEdges");
temp = svg.selectAll("body")
.data(dataset) // LINE 1
.enter()
temp.append("rect")
.attr("width", 4)
.attr("height",12)
.attr("x", function(d) {return x(d.activities[0].start)}) // LINE 2
.attr("y",function(d,i){return i*10;})
.attr("fill","steelblue");
I have following questions :
I want to access START date inside activities but with the code lines (marked LINE 1 and LINE 2) I have written it is giving only 2 rectangles for first start of each activity . WHY?
In LINE 1 can I use dataset.actitvies instead of just dataset? I tried using that , gave me this error :
Uncaught TypeError: Cannot read property '0' of undefined
Upvotes: 2
Views: 5204
Reputation: 1684
Because the length of dataset is 2, so when you join it with your rects you're only going to get 2 rects.
You can use dataset.activities, but you would change LINE 2 to
.attr("x", function(d) {return x(d.start)})
because you've changed the join so that d now refers to the activities. However, if you do that, you're just going to get three rectangles -- the activities for one of your projects.
If you're going to use nested data, you either need to use a nested selection or you need to flatten the data first by adding all activities to a simple array.
var data = [];
for (var i = 0, len = dataset.length; i < len; i++) {
data = data.concat(dataset[i].activities);
}
A nested selection would look something like this:
projects = svg.selectAll("g")
.data(dataset)
.enter().append("g")
.attr("transform", function (d, i) { return "translate(0," + (i * 10) + ")"; }),
rects = projects.selectAll("rect")
.data(function (d) { return d.activities; })
.enter().append("rect")
.attr("height", 12)
.attr("width", 4)
.attr("x", function (d) { return x(d.start); })
EDIT: here's a jsfiddle
Upvotes: 3