admin管理员组

文章数量:1405374

I have a function triggerWave() which makes the points on the canvas animate in the wave form. I am using d3.ease('quad-in') for easing and I would like to use d3.timer() to make the triggerWave() function call over 200ms timeframe. I am out of luck in finding the tutorials or examples on d3.timer.

triggerWave() {
  //function logic
  let count = 0;
  let xScale = d3.scale.linear().range([1,2]); // want the value to change from 1 to 2.
  let zScale = d3.scale.linear().domain([0, 200]); // 200 ms.
  let value = xScale(d3.ease('quad-in')(zScale(count)));
  if(count < 200){
   count++;
   d3.timer(() => triggerWave());
  } else {
    // do something
  }
  this.wave.next({currentFrame: value});
}

When I call d3.timer() as above, the triggerWave() function gets called infinite times and never stops. I want to manipulate or control the time. In my case, I want the timer() to be triggered for 200ms.

How can I understand how to use the d3.timer() function?

I have a function triggerWave() which makes the points on the canvas animate in the wave form. I am using d3.ease('quad-in') for easing and I would like to use d3.timer() to make the triggerWave() function call over 200ms timeframe. I am out of luck in finding the tutorials or examples on d3.timer.

triggerWave() {
  //function logic
  let count = 0;
  let xScale = d3.scale.linear().range([1,2]); // want the value to change from 1 to 2.
  let zScale = d3.scale.linear().domain([0, 200]); // 200 ms.
  let value = xScale(d3.ease('quad-in')(zScale(count)));
  if(count < 200){
   count++;
   d3.timer(() => triggerWave());
  } else {
    // do something
  }
  this.wave.next({currentFrame: value});
}

When I call d3.timer() as above, the triggerWave() function gets called infinite times and never stops. I want to manipulate or control the time. In my case, I want the timer() to be triggered for 200ms.

How can I understand how to use the d3.timer() function?

Share Improve this question edited Aug 2, 2017 at 23:01 halfer 20.4k19 gold badges109 silver badges202 bronze badges asked Aug 2, 2017 at 22:54 TumsTums 5892 gold badges6 silver badges16 bronze badges 1
  • 2 Tums, I wrote an answer and, only after posting it, I noticed that you're using D3 v3. Unfortunately, there is no d3.timeout in v3, but you can do the same approach proposed in my answer with vanilla JS, that is, setTimeout: jsfiddle/gerardofurtado/ffv3r5gn – Gerardo Furtado Commented Aug 3, 2017 at 0:36
Add a ment  | 

3 Answers 3

Reset to default 5

(EDIT: I totally and pletely missed the huge, big "V3" which is right there, in the title of the question. Sorry. I'll keep this answer here as reference for v4 users)

Since you are calling triggerWave inside the triggerWave function itself, you don't need d3.timer, but d3.timeout instead. According to the API, d3.timeout:

Like timer, except the timer automatically stops on its first callback. A suitable replacement for setTimeout that is guaranteed to not run in the background. The callback is passed the elapsed time.

Also, pay attention to the fact that you are reseting count every time the function runs, which will not work. Set its initial value outside the function.

Here is a demo with those changes. I'm calling the function every 200 ms, until count gets to 50:

var p = d3.select("p")
var count = 0;

triggerWave();

function triggerWave() {
  p.html("Count is " + count)
  if (count < 50) {
    count++;
    d3.timeout(triggerWave, 200)
  } else {
    return
  }
}
<script src="https://d3js/d3.v4.min.js"></script>
<p></p>

You can also keep track of the total elapsed time, using the argument passed to triggerWave by d3.timeout:

var p = d3.select("p")
var count = 0;
var elapsed = 0;
var format = d3.format(".2")

triggerWave();

function triggerWave(t) {
  elapsed = t ? elapsed + t : elapsed;
  p.html("Count is " + count + ", and the elapsed time is " + format(elapsed/1000) + " seconds")
  if (count < 50) {
    count++;
    d3.timeout(triggerWave, 200)
  } else {
    return
  }
}
<script src="https://d3js/d3.v4.min.js"></script>
<p></p>

Since you are using D3 v3, and as there is no d3.timeout in v3, you can do the same approach using vanilla JavaScript: setTimeout.

Here is a demo:

var p = d3.select("p")
var count = 0;

triggerWave();

function triggerWave() {
  p.html("Count is " + count)
  if (count < 50) {
    count++;
    setTimeout(triggerWave, 200)
  } else {
    return
  }
}
<script src="https://d3js/d3.v3.min.js"></script>
<p></p>

In version 3, there is no d3.timer.stop() function. You have to return true after a certain period of time to stop the timer.

In Gerardo's answer, he explained fabulously how to use the d3 timeout which would be a valid solution to your problem i.e., to call the function over and over for a certain period of time. But looking at your ments on Gerardo's answer, I think you are looking for something else.

Here's what I came up with and I think this is what you are looking for:

You can create an another function called as activateTriggerWave() which will be invoked on the button click and inside this function, you can call your triggerWave() method using the d3 timer.

function activateTriggerWave() {
  d3.timer(elapsed => {
  this.triggerWave();
  if(elapsed >= 200){
    return true; // this will stop the d3 timer. 
  }
});
}

triggerWave() {
 // here you can do whatever logic you want to implement.
}

I hope this helps.

I use d3.js v3, and the timer can be stopped by any user action. In the d3.js docs it is shown to use it as:

d3.timer(function(elapsed) {
  console.log(elapsed);
  return elapsed >= 1000;
});

I have few examples in which the animation is forever and there is no reason to set a limit on it. Checking the standalone d3.timer which es with a stop(), I found that it behaves quite slow paring it with the default timer included in the v3 toolset, probably for some version inpatibility.

The solution is use is to:

var timer_1_stop=false;

set it as global var accesible from the page scope. Then the timer:

const run=function(){
  //...
  d3.timer(function() {
    voronoi = d3.geom.voronoi(points).map(function(cell) { return bounds.clip(cell); });
    path.attr("d", function(point, i) { return line(resample(voronoi[i])); });

    return timer_1_stop;
  });
}

const stopVoro=function(){
  timer_1_stop=true;
}

It allows to do:

class Menu extends React.Component {
  render(){
    return(<ul>
      <li><span onClick={()=>{stopVoro()}}>StopVoro</span></li>
    </ul>)
  }
}

本文标签: javascriptHow to use timer in d3 V3Stack Overflow