d3.js Y轴未扩展到值

时间:2016-03-18 10:17:59

标签: d3.js

我有一个条形图,它由JSON变量的值填充。该图表是动态的,因为通过计数从SQL查询中检索值。所以我的数据反馈如下:

[{"Fruit":"Apple","COUNT( Fruit )":"12"},{"Fruit":"Orange","COUNT( Fruit )":"6"},{"Fruit":"Pear","COUNT( Fruit )":"1"},{"Fruit":"Blank","COUNT( Fruit )":"1"},{"Fruit":"Pineapple","COUNT( Fruit )":"1"},{"Fruit":"Kiwi","COUNT( Fruit )":"1"}]

在大多数情况下,我的图表似乎正常显示。然而有些人返回超过Y轴的值,我不认为是导致问题的值我认为它的轴不计算正确的高度。例如

如果橙色计数为14,有时Y轴会停在一个小于此值的数字处,并且该列会扩展图形。

通过在谷歌浏览器开发者控制台中查看,我可以看到栏的高度为

<rect id="Orange" y="-520px" x="94px" height="1040px" width="162"></rect>

远远超出我的SVG高度600px - 边距(顶部+底部)80px!

有谁知道为什么我的Y轴没有获得正确的最大值?

代码在这里:

                var canv = document.getElementById("exportCanvas");
                canv.width  = screen.width;
                var margin ={top:40, right:0, bottom:40, left:40},
                    width=screen.width - 250,
                    height=600-margin.top-margin.bottom;


                var jsplit =  jdata.split('"');
                var keyX = jsplit[1];
                var keyY = "";
                var data = JSON.parse(jdata);
                for (k in data[0]) {
                    if (k!=keyX) keyY=k;
                }
                console.log("keyX = " + keyX);


                console.log(keyY);
                console.log(data[0]);




                // scale to ordinal because x axis is not numerical
                var x = d3.scale.ordinal()
                    .domain(['Orange','Apple','Pear'])  //Added this in temporarilly. this should be calculated from the data. 
                    .rangeRoundBands([0, width], 0.25,0.25);

                //scale to numerical value by height
               // var y = d3.scale.linear().range([height, 0]);

                var y = d3.scale.linear()

                    .range([height, 0]);


                console.log(data);
                x.domain(data.map(function(d){ return d[keyX]}));


                y.domain([0, d3.max(data, function(d){return d[keyY]})]);   

                var chart = d3.select("#chart")
                    .append("svg")  //append svg element inside #chart
                    .attr("width", width+ margin.left+margin.right)    //set width
                   // .attr("width", width+(2*margin.left)+margin.right)    //set width
                    .attr("height", height+margin.top+margin.bottom); //set height

                   // .attr("transform", "translate(" + Math.min(width,height) / 2 + "," + Math.min(width,height) / 2 + ")");


                var xAxis = d3.svg.axis()
                    .scale(x)
                    .orient("bottom");  //orient bottom because x-axis will appear below the bars

                var yAxis = d3.svg.axis()
                    .scale(y)
                    .orient("left")
                    .ticks(10).tickFormat(function(d) {
                        if (d % 1 == 0) {
                            return d3.format('.f')(d)
                        } else {
                            return ""
                        }
                    });

                var bar = chart.selectAll("g")
                        .data(data)
                        .enter()
                        .append("g");

                        //you're moving the group and then moving the rect below as well
                        //one or the other not both need to be moved. 
                        //.attr("transform", function(d, i){
                        //    return "translate("+x(d[keyX])+", 0)";
                        //});

                    bar.append("rect")
                        .attr("id", function(d) {
                            return d[keyX];
                        }) 
                        .attr("y", function(d) {
                            return y(d[keyY]) + "px";
                        })
                        .attr("x", function(d,i){
                           //AB - Adjusted this so it correcly places the bar along the X
                           //x.range is an array of x values for each bar
                           //calculated in the var x = line above , with the .rangeRoundBands([0, width], 0.25,0.25);
                           //setting the width of the bars (an equal division of width) with margins of 0.25 at the start
                           //and end of the graph and 0.25 between each bar.
                           return x.range()[i] + margin.left + "px";
                        })


                        .attr("height", function(d) {
                            return height - y(d[keyY]) +"px";

                        })


                        .attr("width", x.rangeBand());  //set width base on range on ordinal data

                    bar.append("text")
                        .attr("x",function(d,i){
                            //similar to above but adding half the width of the bar to the x position 
                            //to roughly center it on the bar. only rough as doesnt take account of length of text.
                            return x.range()[i] + margin.left + (x.rangeBand()/2)+ "px";
                        })
                        .attr("y", function(d) { return y(d[keyY]) +20; })
                        .attr("dy", ".75em")
                        .style("fill","white")
                        .style("font-weight", "bold")
                        .text(function(d) { return d[keyY]; });

                    chart.append("g")
                        .attr("class", "x axis")
                        .attr("transform", "translate("+margin.left+","+ height+")")
                        .call(xAxis);


                    chart.append("g")
                        .attr("class", "y axis")
                        .attr("transform", "translate("+margin.left+",0)")
                        .call(yAxis)
                        .append("text")
                        .attr("transform", "rotate(-90)")
                        .attr("y", 6)
                        .attr("dy", ".71em")
                        .style("text-anchor", "end")
                        .text(keyY);

对于已注释掉的代码表示道歉,我一直在尝试使用它,并尝试将其解决。

1 个答案:

答案 0 :(得分:0)

您需要在数据集刷新时重新计算y.domain()。因此,当您更新数据时,可以尝试以下方法:

y.domain([0, d3.max(data, function(d){return d[keyY]})]);    
chart.select(".y.axis")
    .call(yAxis.scale(y));