Lars
Lars

Reputation: 8458

How do you create a d3 line function that will draw 2 lines for x, y1, y2 data?

I have an array of data in this format:

var data = [{x:0,y1:1, y2:2}, {x:1, y1:2, y2:2},...]

I'd like to use d3 to plot this with the help of the line function.

So, I created 2 paths on my svg container...

var path1 = svg.append("path");
var path2 = svg.append("path");

Now, to draw the first line, I have used:

var lineFunction = d3.svg.line()
                  .x(function(d){return d.x}
                  .y(function(d){return d.y1}
                  .interpolate("linear")

and

path1.attr("d", lineFunction(data))

And that worked great. However, how do I now draw the second line? I can of course create a new lineFunction that returns d.y2 for the y value, but that goes completely against the DRY principle. I think my workflow is not quite the right way to do it, so may I ask how are you actually supposed to do it? In other words, how should I create a line function that will work with both the y1 and y2 data?

Upvotes: 0

Views: 803

Answers (1)

knolleary
knolleary

Reputation: 10117

To expand on the commend from @Lars, the trick here is to first pivot your data to be an array of objects that each represents an individual line.

var newData = [
    {
        name: "y1",
        points: [ { x:0, y:1},{x:1,y:2}]
    },
    {
        name: "y2",
        points: [ { x:0, y:2},{x:1,y:2}]
    },
];

Your lineFunction can then operate generically on x and y:

var lineFunction = d3.svg.line()
              .x(function(d){return d.x}
              .y(function(d){return d.y}
              .interpolate("linear")

You can then bind this data to the elements in your visualisation and add a path for each data entry:

var lines = svg.selectAll(".line").data(newData);

lines.enter().append("path")
             .attr("class","line")
             .attr("d",function(d) {
                 return lineFunction(d.points);
             });

Upvotes: 1

Related Questions