为什么我的D3选择必须在D3代码本身之前?

时间:2013-10-12 10:57:18

标签: javascript svg d3.js

我花了好几个小时试图弄清楚为什么我的代码无效。然后我随意地将我的按钮代码从D3代码(在</script></body>之间的末尾)移到顶部(<script type="text/javascript"><body>之间)。它现在有效,但我不知道为什么。我不想再犯这个错误,也不想在将来迷惑自己。

<body>
<button>Update</button> 

    <script type="text/javascript">

    var w = 500;
    var h = 500;
    var barPadding = 1;

    var dataset = [ ];

    for (var i = 0; i < 14; i++) {var newNumber = Math.round(Math.random() * 70);
    dataset.push(newNumber);}


    //Create SVG element
    var svg = d3.select("body")
            .append("svg")
            .attr("width", w)
            .attr("height", h);

    //Create Scales for Data conversion
    var xScale = d3.scale.linear()
                    .domain([0, d3.max(dataset, function(d,i) {return d;})]) //input
                    .range([0,w]); // output

    var yScale = d3.scale.ordinal()
                    .domain(d3.range(dataset.length))
                    .rangeRoundBands([0, h], 0.05);     //Vertical separation + barpadding

        svg.selectAll("rect")
            .data(dataset)
            .enter()
            .append("rect")
            .attr("x", 3)
            .attr("y", function (d,i) {return yScale(i);})
            .attr("width", function(d,i) {return xScale(d);})
            .attr("height", yScale.rangeBand())
            .attr("fill", function(d) {return "rgb(" + (d * 10) + ", 0,0 )";});

        svg.selectAll("text")
            .data(dataset)
            .enter()
            .append("text")
            .text(function(d) {return d;})
            .attr("x", function(d) {return xScale(d) -15;})
            .attr("y", function(d, i) {return yScale(i) +5 +yScale.rangeBand() / 2;})
            .attr("fill", "white")
            .attr("font-family", "sans-serif")
            .attr("text-anchor", "middle");


            //Create Data Update and transition
        d3.select("button")
            .on("click", function() {

            //New values for dataset
        dataset = [ ];

            for (var i = 0; i < 14; i++) {var newNumber = Math.round(Math.random() * 70);
                dataset.push(newNumber);}

            //Update all rects, and color gradient
        svg.selectAll("rect")
            .data(dataset)
            .transition()
            .attr("x", 3)
            .attr("width", function(d,i) {return xScale(d);})
            .attr("fill", function(d) {return "rgb(" + (d * 10) + ", 0,0 )";});

            //Update text label and position
        svg.selectAll("text")
            .data(dataset)
            .text(function(d) {return d;})
            .attr("x", function(d) {return xScale(d) -15;})
            .attr("y", function(d, i) {return yScale(i) +5 + yScale.rangeBand() / 2;});
    });


    </script>

    </body>

1 个答案:

答案 0 :(得分:0)

如果您说问题中显示的代码有效,并且在<button>元素之前使用<script>元素,那是因为浏览器遇到<script>元素时会执行这些元素解析页面时从上到下。这意味着您使用的任何JavaScript只能引用页面源中较高的元素,因为浏览器还不知道后面的元素。

除非,否则在DOM完成之前,函数中的代码才会被调用,例如,如果您分配DOM ready或onload事件处理程序,或者委派的单击处理程序或其他东西。