How to pass on dynamic delay to d3.interval

Viewed 83

d3.interval takes two parameters, callback and delay,e.g. d3.interval(callback, delay).

I was wondering if it is possible to pass on a dynamic delay for each interval.

For example, in the following, I am asking the interval to run at 1000ms delay. But is there a way I can ask d3.interval to run at 0ms, 1000ms, 2000ms, 3000ms respectively for interval# 1,2,3,4.

I tried like desiredDelay[counterF] but it did not work.

const masterSelection = d3.selectAll('[class^="text"]');
const node = masterSelection.nodes();
const len = node.length - 1;
let counterF = 0;
const del = 1000;
const desiredDelay = [0, 1000, 2000, 3000]

let ticker = d3.interval(
    e => {
        const element = masterSelection['_groups'][0][counterF];
        const selection = d3.select(element).node();
        console.log(selection);
        counterF++;
        (counterF > len) ? ticker.stop(): null

    }, del
)
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
  </head>
  <script type="text/javascript" src="https://d3js.org/d3.v7.min.js"></script>
  <body>
    <div class='text1'>one</div>
    <div class='text2'>two</div>
    <div class='text3'>three</div>
    <div class='text4'>four</div>
  </body>
  <script type="text/javascript" src="prod.js"></script>
</html>

2 Answers

Short answer: you can't.

If you look at the source code you'll see that if the delay is not null...

if (delay == null) return t.restart(callback, delay, time), t;

...it will be coerced to a number using the unary plus operator:

t.restart = function(callback, delay, time) {
    delay = +delay,
    etc...

What you can do is creating your own interval function, which is out of the scope of this answer.

Adapted from this, the following works as desired and is to be used with d3.timeout.

const masterSelection = d3.selectAll('[class^="text"]');
const node = masterSelection.nodes();
const len = node.length - 1;
let counter = 0;
//const del = 1000;
const delay = [0, 1000, 2000, 3000];

function show() {

    const element = masterSelection["_groups"][0][counter];
    const selection = d3.select(element).node();
    console.log(selection);

    counter++;
    if (counter > len) return
    d3.timeout(show, delay[counter]);
}

show();
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
  </head>
  <script type="text/javascript" src="https://d3js.org/d3.v7.min.js"></script>
  <body>
    <div class='text1'>one</div>
    <div class='text2'>two</div>
    <div class='text3'>three</div>
    <div class='text4'>four</div>
  </body>
  <script type="text/javascript"></script>
</html>

Related