我是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>
答案 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=26
和i=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)
})