Search code examples
javascriptd3.jsdelay

Delay to the next data item, appending one by one, time after time


I need only to delay circles (apear one by one), but this delay() is ignored.

  D3_svg.selectAll().data(lst).enter().append("circle")
  .attr('cx', d => d.x).attr('cy', d => d.y)  // position
  .attr("r", 10).style("fill","red")          // layout
  .transition().delay(2000)                   // time to the next

There are many complex suggestions (example), using timer, etc. I need the simplest.


Solution

  • While it's possible to literally append the elements sequentially, with a delay, the necessary code would be too cumbersome for D3, and you'd end up bending over backwards: it seems to me that all you want is to the elements to show up in the screen sequentially, one by one. They can be appended at the same time.

    That being the case, we'll use a simple selection.transition. However, we need to transition some attribute: one cannot transition non-existence to existence, it makes little sense.

    The most simple way to make the element showing up in the screen is transitioning its opacity. For the delay, a function that takes the index (the second argument) of the elements is enough. For instance, one element every 1 second:

    .delay(function (_,i){
        return i * 1000
    });
    

    Here is a basic demo:

    d3.select("svg").selectAll(null)
      .data(d3.range(50).map(() => [Math.random() * 300, Math.random() * 150]))
      .enter()
      .append("circle")
      .attr("r", 5)
      .style("fill", "teal")
      .style("stroke", "white")
      .attr("cx", d => d[0])
      .attr("cy", d => d[1])
      .style("opacity", 0)
      .transition()
      .duration(0)
      .delay(function(_, i) {
        return i * 200
      })
      .style("opacity", 1)
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
    <svg></svg>