Is there a way we could implement an animation loop with this method instead of relying on a global variable named main?

Here is a code snippet where I am trying to replace all main references in animate with this references, in order to avoid using a global variable inside the Main class:

class Main {

    constructor(idDiv) {
        this.div = document.getElementById(idDiv);
        this.sceneManager = new SceneManager(this.div);
    }


    animate() {
        console.log('Main::animate::this', this);
        console.log('Main::animate::main', main);
        requestAnimationFrame(main.animate);
        main.sceneManager.animate();
    }

    execute() {

        new ManageEvents(this.div, this.sceneManager);

        const atla = new Atla();

        const repository = new Repository();

        const loadData = new LoadData(atla, repository);

        loadData.load(this.sceneManager);

        console.log('Main::execute::this', this);
        console.log('Main::execute::main', main);
        this.animate(main.sceneManager);

    }
}


const main = new Main('original');
main.execute();

The existing code creates an animation loop that utilizes THREEjs' animate to render a scene.

The current logs are as follows:

In execute:

Main::execute::this Main {div: div#original.column, sceneManager: SceneManager}div: div#original.columnsceneManager: SceneManager {div: div#original.column, camera: PerspectiveCamera, scene: Scene, controls: T…E.TrackballControls, renderer: WebGLRenderer}__proto__: Object


Main::execute::main Main {div: div#original.column, sceneManager: SceneManager}

In animate, first call:

Main::animate::this Main {div: div#original.column, sceneManager: SceneManager}

Main.js:16 Main::animate::main Main {div: div#original.column, sceneManager: SceneManager}

In animate, subsequent calls:

Main::animate::this null

Main.js:16 Main::animate::main Main {div: div#original.column, sceneManager: SceneManager}

As observed, in the initial call both this and main are identical in both execute and animate functions. However, in subsequent calls, 'this' becomes null in animate while 'main' remains an instance of the Main class. This could be due to the line:

requestAnimationFrame(main.animate);

Which causes the loss of 'this.'

In an attempt to replace main references, I made the following changes:

class Main {

    constructor(idDiv) {
        this.div = document.getElementById(idDiv);
        this.sceneManager = new SceneManager(this.div);
    }


    animate(main) {
        console.log('Main::animate::this', this);
        console.log('Main::animate::main', main);
        requestAnimationFrame(main.animate);
        main.sceneManager.animate();
    }

    execute() {

        new ManageEvents(this.div, this.sceneManager);

        const atla = new Atla();

        const repository = new Repository();

        const loadData = new LoadData(atla, repository);

        loadData.load(this.sceneManager);

        console.log('Main::execute::this', this);
        console.log('Main::execute::main', main);
        this.animate(this);

    }
}


const main = new Main('original');
main.execute();

The output is as below:

First call:

Main::execute::this Main {div: div#original.column, sceneManager: SceneManager}
Main.js:34 Main::execute::main Main {div: div#original.column, sceneManager: SceneManager}
Main.js:15 Main::animate::this Main {div: div#original.column, sceneManager: SceneManager}
Main.js:16 Main::animate::main Main {div: div#original.column, sceneManager: SceneManager}

Second call:

Main::animate::this null
Main.js:16 Main::animate::main 697.568

Main.js:17 Uncaught TypeError: Failed to execute 'requestAnimationFrame' on 'Window': The callback provided as parameter 1 is not a function.
    at animate (Main.js:17)

This issue seems to be related to the line:

    requestAnimationFrame(main.animate);

To resolve this, I attempted:

...
        requestAnimationFrame(main.animate(main));
...

However, this resulted in an infinite loop and obscured visibility to the scene. The logs also showed:

Main::execute::this Main {div: div#original.column, sceneManager: SceneManager}
Main.js:34 Main::execute::main Main {div: div#original.column, sceneManager: SceneManager}
Main.js:15 Main::animate::this Main {div: div#original.column, sceneManager: SceneManager}
Main.js:16 Main::animate::main Main {div: div#original.column, sceneManager: SceneManager}
Main.js:15 Main::animate::this Main {div: div#original.column, sceneManager: SceneManager}
Main.js:16 Main::animate::main Main {div: div#original.column, sceneManager: SceneManager}
Main.js:15 Main::animate::this Main {div: div#original.column, sceneManager: SceneManager}
Main.js:16 Main::animate::main Main {div: div#original.column, sceneManager: SceneManager}
Main.js:15 Main::animate::this Main {div: div#original.column, sceneManager: SceneManager}
Main.js:16 Main::animate::main Main {div: div#original.column, sceneManager: SceneManager}

Please assist me with what I might be doing wrong or how I can rectify this issue?

Answer №1

To ensure that references to this in your animation function always refer to your object, you can use the bind method. This way, it will not default to the window context of requestAnimationFrame.

Here's an illustration with a simple example:

class Test {
  constructor() {
    this.name = "Window doesn't have this name!"
    this.animate = this.animate.bind(this)
  }

  animate() {
    requestAnimationFrame(this.animate)
    console.log(this.name) // window's "name" property is usually empty or undefined
  }
}

let test = new Test()
test.animate() // for output view on the console log

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Unable to invoke the setState function within the onSubmit handler of Formik

Every time I submit my form, I want to display an alert. I attempted to pass my state as a prop to the component, but it didn't work. Here's how my class state looks: this.state = { alert_variant: '', alert_heading: ...

When I try to reload the page, JavaScript ceases to function

Check out this JavaScript code snippet: var input = document.getElementById("password_field"); input.addEventListener("keyup", function(event) { if (event.keyCode === 13) { event.preventDefault(); document.getElementById("l ...

JavaScript: Retrieve the Number of Subscribers on the BroadcastChannel

Is there a way to check if a Broadcast channel exists and see how many subscribers it has? We have a product link, and some Chrome tabs are subscribed to a Broadcast channel. We want to determine the number of listeners. const bc = new window.BroadcastCha ...

The condition for "Else" always remains untouched

This snippet is a segment of my partial view content - <div class="form-group row"> <label for="email" class="col-sm-2 form-control-label">Email address</label> <div class="col-sm-9"> <input type="email" class=" ...

Checking URL validity using JavaScript Regex

I attempted to validate a URL with or without the http protocol, but no matter what I tried, the function kept returning false. I verified my regex string on this website: And it appeared as expected. function isUrlValid(userInput) { var rege ...

Identifying the floor or ground using a webcam in motion: A step-by-step guide

I am currently facing a unique challenge: In my project, I have markers (specifically Hiro, A, Kanji) displayed on banners, and I need to show a 3D model (such as augmented reality) when the marker is recognized. Everything works well so far, but here&apo ...

"Learn the simple trick to quickly deactivate an anchor tag in just one easy

I have a navigation bar with items listed in an unordered list: <ul id="mainN" class="nanGroup" ng-show="lCntr.only == 'mainNav'"> <li > <a class="btn btn-small btn-revert" ng-click="lCntr.profile()"></a> &l ...

There seems to be something off with the behavior of my object-oriented programming

Trying to grasp OOP in JS has been quite challenging for me lately... Here is my attempt so far: var worldClass = function(shape){ this.shape = shape; switch (shape){ case "sphere": var tmpX = n ...

Customizable external URLs in HTML files depending on the environment

Here are the SharePoint URLs for my production, QA, and development environments: Production: QA: Development: I need to adjust relative reference URLs in JS & CSS files (/sites/dev/) for each environment. Is there a way to make this configuration dyna ...

HTML drop-down menu not descending as expected

Recently, I've encountered a simple issue with adding a dropdown menu to the navbar to enable sorting options by price, category, rating, etc. Unfortunately, the dropdown functionality is not working as expected. Despite my efforts to troubleshoot by ...

Merge text inputs to preview content prior to form submission

I've been on the hunt for a solution to display the collective values entered into multiple text box fields as they are being typed. Currently, I have 6 text boxes (description1, description2, description3, description4, description5, description6) wh ...

Use the matrix to transform a sphere or Object3D

Currently, I have a 360° panorama image that is mapped onto the outside of a sphere in order to create a spherical projection with my camera placed inside. However, I am interested in flipping this texture inside-out using a matrix transformation. I am l ...

LocalStorage is limited to storing only the initial element of an array

Whenever I try to retrieve the array from localStorage, it only returns the last value. It seems like it is treating the array as an object. How can I solve this issue? function saveData() { if ($("#forma").valid() == true) { var Name = d ...

Using the react-bootstrap library, I have successfully integrated a Navbar

The navigation bar below is not functioning properly, and the container is causing the links to lead to a 404 error page. I have attempted writing it in various formats: <Nav.Link href="" >Name</Nav.Link> <Nav.Link href={"&qu ...

When attempting to invoke a JavaScript function on JSP, there seems to be no

I am currently developing a web application and delving into the intricacies of how Ajax functions within it. I am encountering an issue where nothing occurs when I attempt to select a category, and no errors are being reported. Within my JSP page: < ...

express includes a 500 error due to the .html extension for the view engine

I have an express app where I've configured my views to use HTML, but behind the scenes, I'm actually utilizing the ejs engine in order to maintain the .html extension. Here is how it's currently set up: app.set('views', path.join ...

Utilizing the HTML button element within an ASP file combined with JavaScript can lead to the reloading of the

I am attempting to create a JavaScript function for an HTML button element. However, I have noticed that it causes the page to reload. Strangely, when I use an input with a button type, everything works perfectly. What could be causing this issue and why a ...

What is the solution for incorporating multiple elements in knockout's applyBindingsToNode function?

I am currently using knockout applyBindingsToNode to dynamically add and remove elements in order to update my html. I need to cut the binding, which is why I am utilizing applyBindingsToNode. In an example I have provided, if you click on the button "Reb ...

Issue with VUE JS: Score not increasing on click event as desired

Greetings! I've been working on a basic game that increments the score by 1 when the user clicks a button. new Vue({ el: '#MyApp', data: { score: '10', }, methods: { ScoreIncre: function(incre) { this.score ...

React JS - State values are not persisting and rendering properly upon clicking

Recently, I followed a step-by-step tutorial on creating a todo list using functional components. However, I encountered an issue when attempting to delete or mark items as complete in the list. In both the deleteHandler and completeHandler functions, I tr ...