Reputation: 6121
I am pretty new to d3. For the moment I am able to draw circles based on an array of data - wow - I know :-) But now I would like to just draw two circles at one time while I animate the whole array. Let's say I have 1000 elements in my array and I want to draw 1 and 2 at the same time, then draw 2 and 3, 3 and 4 and so on. This should get a very pretty animation :-) I have played with functions i index and with exit().remove() but this does not work.
This is what I have:
var w = 500;
var h = 300;
var padding = 20;
var dataset = [
[5, 20], [480, 90], [250, 50], [100, 33], [330, 95],
[410, 12], [475, 44], [25, 67], [85, 21], [220, 88],
[600, 150]
];
//Create SVG element
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
//Create scale functions
var xScale = d3.scale.linear()
.domain([0, d3.max(dataset, function(d) { return d[0]; })])
.range([padding, w - padding * 2]);
var yScale = d3.scale.linear()
.domain([0, d3.max(dataset, function(d) { return d[1]; })])
.range([h - padding, padding]);
//Create circles
svg.selectAll("circle")
.data(dataset.slice(0,2))
.enter()
.append("circle")
.attr("cx", function(d) {
return xScale(d[0]);
})
.attr("cy", function(d) {
return yScale(d[1]);
})
.attr("r",10);
for (var i=0; i<4;i++) {
svg.selectAll("circle").data(dataset.slice(i,i+2)).transition().duration(2000).delay(2000)
.attr("cx", function(d) {
return xScale(d[0]);
})
.attr("cy", function(d) {
return yScale(d[1]);
})
.attr("r", 10);
//svg.selectAll("circle").data(dataset.slice(i,i+1)).exit().remove();
console.log(dataset.slice(i,i+2));
}
But I will get only one single animation instead of 4 .. hmm .. what is going wrong?
Upvotes: 2
Views: 2094
Reputation: 204
The delay function accepts callbacks, so there is no need to wrap your selection in a for loop.
.delay( function(d, i) { (2000*i); } )
Upvotes: 1
Reputation: 1014
Looking at the code, you've got a fixed duration (2s) and a fixed delay (2s). The FOR loop will run instantly, thus queueing all four animations up at once, and thus they are probably all playing at the same time - but (probably) only the last will be visible because you've rebound the data.
try something like:
svg.selectAll("circle")
.delay( (2000*i) )
.data(dataset.slice(i,i+2))
.transition()
.duration(2000)
.attr("cx", function(d) {return xScale(d[0]);})
.attr("cy", function(d) {return yScale(d[1]);})
.attr("r", 10);)
Multiplying the delay by the animation counter should offset each animation, and by putting the delay first, it should the data gets rebound just before starting the animation (thereby stopping the final animation step from rebinding it's data before the first animation has run)
Upvotes: 0