-1

The question could be referred to Three.JS framework, but I think it's a general JS problem.

animate();

function animate() {

    {doSomething}
    requestAnimationFrame( animate );

}

So the function animate() runs every frame and does something.

The question is how to add {doAnotherSomething} to animate() on the fly?

function anEventHappened(){

     //adding some methods to animate

}
SOReader
  • 5,697
  • 5
  • 31
  • 53
VVK
  • 435
  • 2
  • 27
  • When do you want to execute this "other thing"? On what bases? If you simply call `requestAnimationFrame(doOtherThing)` then it will get pushed to the stack of rAF and will get executed after your animate. – Kaiido Dec 07 '19 at 09:15

2 Answers2

2

There are several ways to do this. But you'll somehow have to foresee something in this animate function that can detect that more needs to be done. This "something" could be an array with functions to execute as extras. Initially that array would be empty, but upon some event you could add a function to that list (or remove one from it).

Here is a practical example:

let container = document.querySelector("pre");
let todoList = []; // <--- list of functions to execute also as extras
animate();

function animate() {
    todoList.forEach(f => f()); // execute whatever is in the todo-list
    moveText(container);
    requestAnimationFrame(animate);
}

document.querySelector("button").onclick = function anEventHappened() {
    let newContainer = document.createElement("pre");
    newContainer.textContent = Math.random();
    document.body.appendChild(newContainer);
    todoList.push(() => moveText(newContainer)); // add something extra
}

// Helper function to perform some HTML-text manipulation
function moveText(what) {
    what.textContent = what.textContent.includes("<") ? what.textContent.slice(1)
        : what.textContent.length < 60 ? " " + what.textContent
        : what.textContent.replace(/ (\S)/, "<$1");
}
<button>Do extra</button>
<pre>phrase</pre>
trincot
  • 317,000
  • 35
  • 244
  • 286
1

It's quite easy once you know what to look for.

A simplest solution is to keep a collection of functions to be called every time (a collection of strategies)

In order not to share this collection among the whole code base you can apply Subscriber - Publisher approach where your module containing animate subscribes to events in the system that shall change what is to be rendered on the screen.

Here's a good reference about basic design patterns: https://refactoring.guru/design-patterns/

So... going back to your original question, what you can do is to send an event with a callback in it dispatchEvent({ type: 'render'; strategy: <some_function> }) and animate's module will listen to such events .addEventListener('render', event => strategies.push(event.strategy)).

Remarks:

  • Don't forget to remove old strategies.
  • strategies could be a dictionary instead of an array. In that case event render should also have some sort of a key to prevent multiple identical strategies from been pushed to the "queue"

https://threejs.org/docs/index.html#api/en/core/EventDispatcher

SOReader
  • 5,697
  • 5
  • 31
  • 53