You are correct: the for loop will run to the end almost instantly, and it will simply call that bunch of transitions at the same time, which, of course, will not work.

There are some different solutions here. Good news is that transition().on("end"... is just one of them, you don't need to use it if you don't want.

My favourite one is creating a function that you call repeatedly with setTimeout or, even better, with d3.timeout.

This is the logic of it:

var counter = 0;//this is, of course, a counter

function loop(){

    //if there is a data element for the next counter index, call 'loop' again:
    if(data[counter + 1]){ d3.timeout(loop, delay)}

    //access the data using the counter here,
    //and manipulate the selection

    //increase the counter


Have a look at this demo:

var data = [30, 400, 170, 280, 460, 40, 250];
var svg ="body")
  .attr("width", 500)
  .attr("height", 100);
var circle = svg.append("circle")
  .attr("cy", 50)
  .attr("cx", 250)
  .attr("r", 10)
  .attr("fill", "tan")
  .attr("stroke", "black");

var counter = 0;


function loop() {
  if (data[counter + 1]) {
    d3.timeout(loop, 1000)
    .attr("cx", data[counter]);
<script src=""></script>

Related Query

More Query from same tag