Isaac
Isaac

Reputation: 2721

How to wrap d3.svg.line?

I have a webpage with multiple sparklines in it. The user selects certain parameters to control the sparklines, some require loading data from the server, and others don't require loading new data, for example, changing chart type (line, area, bar, etc).

I dont want to reload the whole chart for those parameters, and so I've been trying to manipulate the paths, but I am stuck because I also need to get the original data of each path to rebuild x and y functions as well as my custom built color schema function which is based on a threshold that I compute from the data.

This is how I build the paths:

var chart = d3.svg.line()
    .x(function(d,i) { return x(i); })
    .y(function(d) { return height-y(d); })
    .interpolate('basis');
g.append("path")
    .datum(data)
    .attr("class", "chart-path-" + me.id)
    .attr("d", chart);

This is how I want to update it:

var line = function(data) {
    return d3.svg.line()
        .x(function(d,i) {
            var x = d3.scale.linear().domain([0, data.length]).range([0, width]);
            return x(i);
        })
        .y(function(d, i) {
            var y = d3.scale.linear().domain([0, d3.max(data)]).range([0, height]);
            return height-y(d);
        })
        .interpolate('basis');
}
d3.selectAll(".chart-path-" + me.id)
    .attr("d", function(data) { return line(data); });

The reason I am wrapping the line function is because d3.svg.line doesnot keep the original data passed to it, see the source code here. But it seems like d3 does not accept a function. It throws this error:

Error: Problem parsing d="function n(n){function a(){s.push("M",u(t(f),l))}for(var o,s=[],f=[],h=-1,d=n.length,g=c(e),p=c(r);d>++h;)i.call(this,o=n[h],h)?f.push([+g.call(this,o,h),+p.call(this,o,h)]):f.length&&(a(),f=[]);return f.length&&a(),s.length?s.join(""):null}"

I read that it expects a path or a path generated by d3 helper methods (line, area, etc) which is what I am returning in my function. How can I do this? Am I working in the wrong direction? Please ask if something is not clear.

Upvotes: 0

Views: 415

Answers (1)

nrabinowitz
nrabinowitz

Reputation: 55688

The d3.svg.line component returns a function, but you need to call that function on your data to get a path string. Try something like:

var line = function(data) {
    var generator = d3.svg.line()
        .x(function(d,i) { ... })
        .y(function(d, i) { ...})
        .interpolate('basis');
    return generator(data);
}

D3 is trying to assign the generator function itself to the d attribute, coercing it to a string, hence the weird error.

Upvotes: 2

Related Questions