Search code examples
javascriptd3.jsscale

d3 scale.linear(): pass data as parameter


I'm building multiple bar charts with d3, and would like to apply the same scale based on the input data, which consists of different JSON arrays, for each chart. To find the maximum value of each array, I wrote this function:

var maxInArray = function (dataArray,propertyName) {
    var result = d3.max(dataArray, function(d) { 
        return +d[propertyName]; 
    });
    return result;
};

To find the bar width, I use:

var barLength = d3.scale.linear()
    .domain([0, maxInArray(myArray,"myProperty")])
    .range([0, 400]);

Finally, for the chart:

d3.select(".mybarchart")
        .selectAll("div")
        .data(myArray)
        .enter().append("div")
        .style("width", function(d) { return barLength(d.myProperty) + "px"; })
        .text(function(d) { return d.title+" ("+d.propertyName + ")"; });

But this approach means barLength still has myArray hard-coded in it.

What I'd rather do is to pass the current value, myArray, and myProperty into a function like this:

var barLengthForValue = function (value,dataArray,propertyName) {
    var maxWidth = 400;
    var result = d3.scale.linear()
    .domain([0, maxInArray(dataArray,propertyName)])
    .range([0, maxWidth]);
    return result;
};

To use barLengthForValue for every JSON array I have. But

console.log("barLengthForValue: ",barLengthForValue(10,myArray,"myParameter"));

Returns

function i(n){return o(n)}

Presumably because d3.scale.linear() can't find the parameter it needs to do the calculation.

I read a lot of tutorials on the matter, but none of them does what I want. They all use d3.scale with a fixed data array.

Is what I am trying possible? Specifically, can I "extend" d3.scale.linear() in this fashion?

And a JavaScript question (I guess): How does d3.scale.linear() "extract" the parameter 10 here?

var scale= d3.scale.linear();
scale(10);

Understanding this might help me to understand how to improve barLengthForValue().


Solution

  • The only change you need to make is to return result(value) instead of result -- at the moment you're returning the scale object, which needs to be applied to a value to give the mapped value.