使用d3更新我的条形图时出错

时间:2015-11-22 06:21:11

标签: javascript d3.js

我遇到这个问题的时候,虽然我有d3欠控制...当我使用空数组数据更新我的barChart时,我无法找出我的代码崩溃的原因......

这是我的代码:

<!DOCTYPE html>
<html>
<head>
    <title>Simple tables in D3</title>
    <meta charset="utf-8">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js" charset="utf-8"></script>
    <style type="text/css">

        .chart rect {
            fill: steelblue;
        }

        .axis path,
        .axis line {
            fill: none;
            stroke: #000;
            shape-rendering: crispEdges;
        }

        .x.axis path {
            display: none;
        }

        .axis {
            font: 10px sans-serif;
        }

    </style>
</head>
<body>

    <svg class="chart">
    </svg>

    <script>
        var scanCounters = JSON.parse("[{\"scan\":\"111\",\"repetition\":3},{\"scan\":\"222\",\"repetition\":2},{\"scan\":\"333\",\"repetition\":4},{\"scan\":\"123\",\"repetition\":2},{\"scan\":\"456\",\"repetition\":1},{\"scan\":\"789\",\"repetition\":1}]");

        var scanCounters2 = JSON.parse("[{\"scan\":\"111\",\"repetition\":8},{\"scan\":\"222\",\"repetition\":6},{\"scan\":\"333\",\"repetition\":5},{\"scan\":\"123\",\"repetition\":3}]");

        var scanCounters3 = JSON.parse("[]");

        var columns = ["scan", "repetition"];

        var margin = {top: 20, right: 30, bottom: 30, left: 40};

        var width = 960;
        var height = 500;

        var innerWidth = width - margin.left - margin.right;
        var innerHeight = height - margin.top - margin.bottom;

        var bcScan = barChart(600, 400, "chart");
        bcScan.update(scanCounters);

        setTimeout(function(){
            bcScan.update(scanCounters2);
            }, 1000);

        setTimeout(function(){
            bcScan.update(scanCounters3);
            }, 2000);

    function barChart(w, h, node) {

        var bC = {};

        var margin = {top: 20, right: 20, bottom: 30, left: 40},
                width = w - margin.left - margin.right,
                height = h - margin.top - margin.bottom;

        var x = d3.scale.ordinal()
                .rangeRoundBands([0, width], .1);

        var y = d3.scale.linear()
                .range([height, 0]);

        var xAxis = d3.svg.axis()
                .scale(x)
                .orient("bottom");

        var yAxis = d3.svg.axis()
                .scale(y)
                .orient("left");

        var svg = d3.select("." + node)
                .attr("width", width + margin.left + margin.right)
                .attr("height", height + margin.top + margin.bottom)
                .append("g")
                .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

        svg.append("g")
                .attr("class", "x axis")
                .attr("transform", "translate(0," + height + ")");

        svg.append("g")
                .attr("class", "y axis")
                .append("text")
                .attr("transform", "rotate(-90)")
                .attr("y", -40)
                .attr("dy", ".71em")
                .style("text-anchor", "end")
                .text("Frequency");

        bC.update = function(data) {

            x.domain(data.map(function (d) {
                return d[Object.keys(d)[0]];
            }));
            y.domain([0, d3.max(data, function (d) {
                return d[Object.keys(d)[1]];
            })]);

            svg.select(".x.axis")
                    .transition()
                    .duration(300).call(xAxis)
                    .selectAll("text")
                    .style("text-anchor", "end")
                    .attr("dx", "-.8em")
                    .attr("dy", ".15em")
                    .attr("transform", "rotate(-65)");

            svg.select(".y.axis")
                    .transition()
                    .duration(300)
                    .call(yAxis);

            var bars = svg.selectAll(".bar").data(data, function (d) {
                return d[Object.keys(d)[0]];
            });

            bars.exit()
                    .transition()
                    .duration(300)
                    .attr("y", y(0))
                    .attr("height", height - y(0))
                    .style('fill-opacity', 1e-6)
                    .remove();

            bars.enter()
                    .append("rect")
                    .attr("class", "bar")
                    .attr("y", y(0))
                    .attr("height", height - y(0));

            var trans = bars.transition().duration(300).attr("x", function (d) {
                return x(d[Object.keys(d)[0]]);
            });

            trans.attr("width", x.rangeBand())
                    .attr("y", function (d) {
                        return y(d[Object.keys(d)[1]]);
                    })
                    .attr("height", function (d) {
                        return height - y(d[Object.keys(d)[1]]);
                    });

        };

        return bC;
    }

        </script>
</body>
</html>

问题是当我调用bcScan.update(scanCounters3);时,scanCounters3是一个空数组。

这是错误消息:

  

错误:属性高度的值无效=&#34; NaN&#34;

     

错误:属性y =&#34; NaN&#34;

的值无效

QUESTON:有人可以帮我理解崩溃的原因吗?

感谢

1 个答案:

答案 0 :(得分:1)

@EthanJewett,是正确的,如果您在每次迭代时查看y.domain()

[0, 4]
[0, 8]
[0, NaN]

所以在你的最后一次迭代中,退出转换是在NaN上进行数学运算:

.attr("y", y(0))
.attr("height", height - y(0))

我会完全删除这些行并进行退出转换:

       bars.exit()
         .transition()
         .duration(300)
         .style('fill-opacity', 1e-6)
         .remove();