Reputation: 1653
So I guess my main issue is that my data isn't EXACTLY like all of the d3 demos out there. I made a plugin that normalizes all my data into the form:
[{"name":"someName", "values":[{x1, y1}, {x2, y2}, ... {xn, yn}, ...]
So this code works just fine for the line:
var line = d3.svg.line()
.x(function(d) { return x(d.x); })
.y(function(d) { return y(d.y); });
// data is a list of objects, each of which respresents a line
var series = svg.selectAll(".series")
.data(dataSimplified)
.enter().append("g")
.attr("class", "series");
series.append("path")
.attr("class", "line")
// the following function requires a list of things, like [{x0, y0}, {x1, y1}, ... {xn, yn}]
.attr("d", function(d) { return line(d.values); })
.style("stroke", function(d) { return color(d.name); });
So it basically iterates over each "values" field and does the line function to get the x and y. But if I do a similar thing for the points, it doesn't work! The following, however, DOES work:
// add points
for(var i=0; i<dataSimplified.length; i++){
for(var j=0; j<dataSimplified[i].values.length; j++){
svg.append("circle")
.attr("r", 3.5)
.attr("cx", function(d){ return x(dataSimplified[i].values[j].x); })
.attr("cy", function(d){ return y(dataSimplified[i].values[j].y); })
.attr("fill", function(d){ return color(dataSimplified[i].name); });
}
}
Is there a better way to do this than adding the points one by one? Why doesn't cx accept a list like d did for the path?
Upvotes: 1
Views: 498
Reputation: 19377
You can call .data
again on for nested selections (in this case the <circle>
tags nested inside the <g>
tag). Something like this:
series.selectAll('circle')
.data(function(d, i, j) { return d.values; })
.enter().append('circle')
.attr("r", 3.5)
.attr("cx", function(nd){ return x(nd.x); })
.attr("cy", function(nd){ return y(nd.y); })
.attr("fill", function(nd, i, j){ return color(dataSimplified[j].name); });
The reason it seems inconsistent between line and circle is that D3 is only a thin layer over the underlying DOM nodes (html or svg), and doesn't abstract that away from you. So in svg, <path>
is a single tag which contains an internal list of points, while <circle>
is just one circle. So your structure for one series will be something like this (assuming you have three data points).
<g><path/><circle/><circle/><circle/></g>
And so your code will reflect the same kind of structure.
Upvotes: 4