18

I'm working on some personal project by Three.js. I'm using requestAnimationFrame function. I want to call a function each 2 seconds. I've search but I couldn't find anything useful.

My code is like this:

function render() {
   // each 2 seconds call the createNewObject() function
   if(eachTwoSecond) {
      createNewObject();
   }
   requestAnimationFrame(render);
   renderer.render(scene, camera);
}

Any Idea?

Damjan Pavlica
  • 31,277
  • 10
  • 71
  • 76
Siamak Motlagh
  • 5,028
  • 7
  • 41
  • 65

5 Answers5

24

requestAnimationFrame passes single parameter to your callback which indicates the current time (in ms) when requestAnimationFrame fires the callback. You can use it to calculate time interval between render() calls.

var last = 0; // timestamp of the last render() call
function render(now) {
    // each 2 seconds call the createNewObject() function
    if(!last || now - last >= 2*1000) {
        last = now;
        createNewObject();
    }
    requestAnimationFrame(render);
    renderer.render(scene, camera);
}
hindmost
  • 7,125
  • 3
  • 27
  • 39
2

I had a similar problem and came up with this solution:

let t = 0
const interval = 2 * 60 // there are 60 ticks per second

function render() {
  if (++t % interval == 0)
    doSomething()

  requestAnimationFrame(render)
}

UPDATE: This solution is framerate dependent, so it is not good.

Damjan Pavlica
  • 31,277
  • 10
  • 71
  • 76
  • 4
    If you have a 144hz frame rate, it will last 1 second. And on a 30hz screen (like an unplugged laptop), it will last 0.5 second. You can't rely on framerate as a time unit. – Quentin D Jan 19 '21 at 13:58
2

this function will print a number every 2 seconds

let last = 0;
let num = 0;
let speed = 2;

function main(timeStamp) {
  let timeInSecond = timeStamp / 1000;

  if (timeInSecond - last >= speed) {
    last = timeInSecond;
    console.log(++num);
  }

  requestAnimationFrame(main);
}

main();
Abdulnaser
  • 31
  • 3
0

Since requestAnimationFrame will give you an available frame in 60fps (if your browser can keep up with it) it seems perfectly fine to wait 2 seconds and request a frame. This way the browser will give you a frame exactly after these 2 seconds, which in most cases will be in an instant:

        function render() {
            // each 2 seconds call the createNewObject() function
            createNewObject();
            renderer.render(scene, camera);
        }

        setInterval(function () {
            requestAnimationFrame(render);
        }, 2000);
Georgi-it
  • 3,676
  • 1
  • 20
  • 23
  • Thanks, But I don't want to decrease fps. I want fps to remain 60. there are other animations exist in the project which I need them to be smooth while animating. decreasing fps is not a solution I guess. – Siamak Motlagh Apr 20 '15 at 09:37
  • `setInterval` has tons of issues when used in this way which cause huge performance problems on top of ruining your animation. Instead you should use `requestAnimationFrame`. More info: https://blog.webdevsimplified.com/2021-12/request-animation-frame/ – bgrand-ch Jul 06 '23 at 11:27
0

Simple JS Timer that runs every given seconds

Modification of the MDN Example --> Here.

/*
<div id="test">
        <h1>Hello World</h1>
</div>
*/
const element = document.getElementById('test');
let start, previousTimeStamp;


timerConfig = {
    frequency: 1, // Seconds
    stopAt: 10, // Seconds,
    pos: 1,  // px
    posStep: 10,  // px
    updatePos: () => {
        timerConfig.pos = timerConfig.pos + timerConfig.posStep;
    }
}

function timer(timestamp) {    
    if (start === undefined)  start = timestamp;
    if (previousTimeStamp === undefined)  previousTimeStamp = timestamp;
    const seconds = timerConfig.frequency*1000;
    const tick = timestamp - previousTimeStamp; 

    function trigger() {
        element.style.transform = 'translateX(' + timerConfig.pos + 'px)';
    }

    if (tick >= seconds) {
        trigger();
        previousTimeStamp = timestamp; // Updating The Timer each second
        timerConfig.updatePos();
    }
    if (timestamp < timerConfig.stopAt*1000) requestAnimationFrame(timer); // 10 Seconds    
    
}

requestAnimationFrame(timer);
Federico Baù
  • 6,013
  • 5
  • 30
  • 38