简体   繁体   中英

d3 v4 js : attribute error

I'm very new to data vizualisation and JavaScript and I'm trying to build a bar chart histogram using d3 v4. I was working first working on d3 v3 and everything was going so well but I've got informed that I needed to work on v4.

Here is a piece of my code :

        ...
    // create function for x-axis mapping.
    var x = d3.scaleBand().rangeRound([0, hGDim.w]).padding(0.1)
            .domain(fD.map(function(d) { return d[0]; }));

    var xAxis = d3.axisBottom()
    .scale(x);


    // Create function for y-axis map.
    var y = d3.scaleBand().rangeRound([0, hGDim.h])
            .domain([0, d3.max(fD, function(d) { return d[1]; })]);

    var yAxis = d3.axisBottom()
    .scale(y);

    // Create bars for histogram to contain rectangles and freq labels.
    var bars = hGsvg.selectAll(".bar").data(fD).enter()
            .append("g").attr("class", "bar");

    //create the rectangles.
    bars.append("rect")
        .attr("x", function(d) { return x(d[0]); })
        .attr("y", function(d) { return y(d[1]); })
        .attr("width", x.bandwidth())
        .attr("height", function(d) { return hGDim.h - y(d[1]); })
        .attr('fill',barColor)
        .on("mouseover",mouseover)// mouseover is defined below.
        .on("mouseout",mouseout);// mouseout is defined below.

    //Create the frequency labels above the rectangles.
    bars.append("text").text(function(d){ return d3.format(",")(d[1])})
        .style("font-family", "sans-serif")
        .attr("x", function(d) { return x(d[0])+x.bandwidth()/2; })
        .attr("y", function(d) { return y(d[1])-5; })
        .attr("text-anchor", "middle");
        ...

When trying to run this, I have this 2 errors :

Error: attribute height: Expected length, "NaN".

And it tells me that it's on this line :

.attr("height", function(d) { return hGDim.h - y(d[1]); })

hGDim.h being a number

I also have this error :

Error: attribute y: Expected length, "NaN".

And it tells me that it's on this line :

.attr("y", function(d) { return y(d[1])-5; })

I didn't put all my code (271 lines), I'm not sure it's needed here.

Do you have any idea from where could these errors come from ? I feel that I'm trying to add 2 variables of different types... However, it was working well on v3.

You are treating your y scale like a continuous scale, but it needs to be ordinal like your x scale (scaleBand() is ordinal). Try this:

var y = d3.scaleBand()
    .rangeRound([0, hGDim.h])
    .domain(fD.map(function(d) {return d[1];}));

Then, you must modify the create rectangle code as follows:

bars.append("rect")
    .attr("x", function(d) { return x(d[0]); })
    .attr("y", function(d) { return y(d[1]); })
    .attr("width", x.bandwidth())
    .attr("height", y.bandwidth())
    .attr('fill', barColor)
    .on("mouseover", mouseover)
    .on("mouseout", mouseout);

Here is a minimal example, assuming d[0] and d[1] are coordinates on the heatmap:

 var data = [[1, 1, "red"], [1, 2, "blue"], [1, 3, "green"], [2, 1, "navy"], [2, 2, "yellow"], [2, 3, "orange"], [3, 1, "red"], [3, 2, "blue"], [3, 3, "red"]], svg = d3.select("svg"), w = 500, h = 500, x = d3.scaleBand() .rangeRound([0, w]) .padding(0.1) .domain(data.map(function(d) {return d[0];})), y = d3.scaleBand() .rangeRound([0, h]) .padding(0.1) .domain(data.map(function(d) {return d[1]})), xAxis = d3.axisBottom() .scale(x), yAxis = d3.axisBottom() .scale(y), bars = svg.selectAll(".bar") .data(data).enter() .append("g") .attr("class", "bar"); bars.append("rect") .attr("x", function(d) { return x(d[0]); }) .attr("y", function(d) { return y(d[1]); }) .attr("width", x.bandwidth()) .attr("height", y.bandwidth()) .style("fill", function(d) { return d[2]; }); 
 <script src="https://d3js.org/d3.v4.js"></script> <svg height="500px", width="500px"></svg> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM