For循环在D3.js中不起作用

时间:2016-07-17 05:45:10

标签: javascript for-loop d3.js

我是Javascript和D3.js的新手,并试图在for循环中连续更改圆圈元素。 这意味着每秒都要改变圆的半径,但事实证明半径只是跳到50,忽略了26到49。

这是我的代码。

<!DOCTYPE html>
<meta charset="utf-8">
<style>

</style>
<body>
<script src="//d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script src="//d3js.org/topojson.v1.min.js"></script>
<script>
    var width = 960,
            height = 1160;
    var svg = d3.select("body").append("svg")
            .attr("width", width)
            .attr("height", height);

    svg.append("circle").attr("cx", 100).attr("cy", 100).attr("r", 25).style("fill", "purple").attr('id','cc');

    for(i=26;i<=50;i++){
        var now=d3.select('#cc');
        now.transition().duration(1000).attr("r",i);
    }
</script>

3 个答案:

答案 0 :(得分:2)

在JavaScript中,当你说:

for(i=26;i<=50;i++){
    var now=d3.select('#cc');
    now.transition().duration(1000).attr("r",i);
}

不要认为for循环会等到i=26转换完成后再转移到i=27。实际上,它为now.transition().duration(1000).attr("r",i);调用语句i=26,然后IMMEDIATELY移动到循环的下一次迭代。由于循环的i=26i=50迭代之间的时间差是无穷小的(速度仅受处理器的速度限制,今天是GHz),您可以认为调用了所有转换一起观察最后一个的影响,立即

这样做的一种方法是在每次调用之前设置一个时间延迟,并记住,时间延迟必须是ABSOLUTE,因为几乎在同一时刻调用所有迭代。例如,

第一个声明在0秒后调用 第二个声明在1秒后调用 第二个声明在2秒后调用。

只有这样,你才会看到来电之间的相对差异为1秒。

另一种方法是使用setTimeout()例程递归执行。 建议使用此方法。

var i = 26;

function myLoop () {
    setTimeout(function () {
        var now=d3.select('#cc');
        now.transition().duration(1000).attr("r",i);
        i++;
        if (i < 50) {
            myLoop();
        }
    }, 1000) // change this time (in milliseconds) to whatever you desire
}

myLoop(); // first call

答案 1 :(得分:0)

问题是你的for循环只是立即迭代所有这些变化。您需要在每次拨打transition之间等待1秒钟。这样的事情应该有用,虽然在当前转换结束后d3或许有更好的方法可以做某事吗?

function changeRadius(i) {
    d3.select('#cc').transition().duration(1000).attr("r", i);

    // "loop" by calling ourselves 1 second later with the next radius
    if (i < 50) {
        window.setTimeout(function () {
            changeRadius(i + 1);
        }, 1000);
    }
}
// first change
changeRadius(26);

关注the d3 documentation,我认为这可行:

var current = d3.select('#cc');
for (var i = 26; i <= 50; i++) {
    current = current.transition().duration(1000).attr("r", i);
}

答案 2 :(得分:0)

您可以补间半径,而不是创建多个过渡或弄乱延迟。 Demo

d3.select('#cc')
  .transition()
  .duration(25*1000)
  .attrTween('r', function() {
      return d3.interpolateNumber(25, 50)
  })