Why is a method for animation in Three.js + TypeScript only executed once?

This piece of code is currently functioning correctly, except for one issue - the lack of animation. The code draws an axis and a cube, but the cube should be animated. I only see the "animate" string in the console once.

Solution: Replace this line

requestAnimationFrame(() => this.animate);
with this one
requestAnimationFrame(this.animate.bind(this));
https://codepen.io/8Observer8/pen/oWoXyz

/// <reference path="../node_modules/@types/three/index.d.ts" />

//import * as THREE from "three";
// this line does't work. Error: Cannot find module 'three' from ...

// https://github.com/pinqy520/three-typescript-starter/blob/master/src/index.ts

class Game
{
    private _scene: THREE.Scene;
    //private _canvas: HTMLCanvasElement;
    private _camera: THREE.PerspectiveCamera;
    private _renderer: THREE.WebGLRenderer;
    private _axis: THREE.AxisHelper;
    private _light: THREE.DirectionalLight;
    private _light2: THREE.DirectionalLight;
    private _material: THREE.MeshBasicMaterial;
    private _box: THREE.Mesh;

    public constructor()
    {
        //this._canvas = <HTMLCanvasElement>document.getElementById(canvasElement);
        this._scene = new THREE.Scene(); // create the scene
        // create the camera
        this._camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
        this._renderer = new THREE.WebGLRenderer();
        this._axis = new THREE.AxisHelper(10); // add axis to the scene
        this._light = new THREE.DirectionalLight(0xffffff, 1.0); // add light1
        this._light2 = new THREE.DirectionalLight(0xffffff, 1.0); // add light2
        this._material = new THREE.MeshBasicMaterial({
            color: 0xaaaaaa,
            wireframe: true
        });
        // create a box and add it to the scene
        this._box = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1), this._material);
    }

    public createScene(): void
    {
        // set size
        this._renderer.setSize(window.innerWidth, window.innerHeight);
        document.body.appendChild(this._renderer.domElement); // add canvas to dom
        this._scene.add(this._axis);
        this._light.position.set(100, 100, 100);
        this._scene.add(this._light);
        this._light2.position.set(-100, 100, -100)
        this._scene.add(this._light2);
        this._scene.add(this._box)
        this._box.position.x = 0.5;
        this._box.rotation.y = 0.5;

        this._camera.position.x = 5;
        this._camera.position.y = 5;
        this._camera.position.z = 5;

        this._camera.lookAt(this._scene.position);
    }

    public animate(): void
    {
        requestAnimationFrame(this.animate.bind(this));
        this._render();
    }

    private _render(): void
    {
        let timer = 0.002 * Date.now();
        this._box.position.y = 0.5 + 0.5 * Math.sin(timer);
        this._box.rotation.x += 0.1;
        this._renderer.render(this._scene, this._camera);
    }
}

window.onload = () =>
{
    let game = new Game();
    game.createScene();
    game.animate();
}

Answer №1

After some discussion in the comments, I've put together the following TypeScript code snippet to demonstrate how you can make a certain functionality work. I've included an additional console.log inside the _render method to show the output.

class Game {
    public animate()
    {
        console.log("animate()");
        this._render();
        requestAnimationFrame(()=>this.animate());

    }

    private _render(): void
    {
        console.log("From _render")

    }
}

let game = new Game();
game.animate();

For further clarity and understanding, you can check out the example on the TypeScript Playground here. Make sure to open your console to view the results when running the example.

Answer №2

Unique Solution 1:

window.requestAnimationFrame(()=>this.startAnimation());

Unique Solution 2:

window.requestAnimationFrame(() => {this.startAnimation();});

Unique Solution 3:

window.requestAnimationFrame(this.startAnimation.bind(this));
https://codepen.io/8Observer8/pen/oWoXyz

// <reference path="../node_modules/@types/three/index.d.ts" />

//import * as THREE from "three";
// this line doesn't work. Error: Cannot find module 'three' from ...

// https://github.com/pinqy520/three-typescript-starter/blob/master/src/index.ts

class InteractiveGame
{
    private _scene: THREE.Scene;
    //private _canvas: HTMLCanvasElement;
    private _camera: THREE.PerspectiveCamera;
    private _renderer: THREE.WebGLRenderer;
    private _axis: THREE.AxisHelper;
    private _light: THREE.DirectionalLight;
    private _light2: THREE.DirectionalLight;
    private _material: THREE.MeshBasicMaterial;
    private _box: THREE.Mesh;

    public constructor()
    {
        //this._canvas = <HTMLCanvasElement>document.getElementById(canvasElement);
        this._scene = new THREE.Scene(); // create the scene
        // create the camera
        this._camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
        this._renderer = new THREE.WebGLRenderer();
        this._axis = new THREE.AxisHelper(10); // add axis to the scene
        this._light = new THREE.DirectionalLight(0xffffff, 1.0); // add light1
        this._light2 = new THREE.DirectionalLight(0xffffff, 1.0); // add light2
        this._material = new THREE.MeshBasicMaterial({
            color: 0xaaaaaa,
            wireframe: true
        });
        // create a box and add it to the scene
        this._box = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1), this._material);
    }

    public setupScene(): void
    {
        // set size
        this._renderer.setSize(window.innerWidth, window.innerHeight);
        document.body.appendChild(this._renderer.domElement); // add canvas to dom
        this._scene.add(this._axis);
        this._light.position.set(100, 100, 100);
        this._scene.add(this._light);
        this._light2.position.set(-100, 100, -100)
        this._scene.add(this._light2);
        this._scene.add(this._box)
        this._box.position.x = 0.5;
        this._box.rotation.y = 0.5;

        this._camera.position.x = 5;
        this._camera.position.y = 5;
        this._camera.position.z = 5;

        this._camera.lookAt(this._scene.position);
    }

    public startAnimation(): void
    {
        window.requestAnimationFrame(this.startAnimation.bind(this));
        this.renderFrame();
    }

    private renderFrame(): void
    {
        let timer = 0.002 * Date.now();
        this._box.position.y = 0.5 + 0.5 * Math.sin(timer);
        this._box.rotation.x += 0.1;
        this._renderer.render(this._scene, this._camera);
    }
}

window.onload = () =>
{
    let interactiveGame = new InteractiveGame();
    interactiveGame.setupScene();
    interactiveGame.startAnimation();
}

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

Error: Trying to access a property that does not exist on an undefined object (retrieving 'kind

Currently, I am working on a project using angular-CLI. When I attempted to create a new module yesterday, an error popped up in the terminal saying Cannot read properties of undefined (reading 'kind') (only this error there wasn't an ...

Retrieve information from an XML document

I have some XML content that looks like this: <Artificial name="Artifical name"> <Machine> <MachineEnvironment uri="environment" /> </Machine> <Mobile>taken phone, test when r1 100m ...

It is impossible to declare a class attribute that has the same type as the class itself, creating a self-referencing hierarchy

My Angular model class has properties that reference the class itself: export class ItemCategory { constructor( public parentCategory?: ItemCategory, public subCategories?: ItemCategory[], public name?: string, public description?: st ...

Utilize dynamic components to load varying data sets multiple times

Is there a way to dynamically load a component multiple times and pass data based on certain values so that it will display with real-time information? I came across an example at the following link: In this example, there is a messageComponent with a "m ...

Utilize tree-shaking functionality within your TypeScript project

In the process of developing a TypeScript telemetry library using OpenTelemetry, I am exploring ways to incorporate tree-shaking to allow consumers to selectively import only the necessary modules and minimize the overall bundle size. The project directory ...

Discover the accurate `keyof` for a nested map in TypeScript

Here is the code snippet I'm working on: const functions={ top1: { f1: () => 'string', f2: (b: boolean, n: number) => 1 }, top2: { f3: (b: boolean) => b } } I am looking to define an apply f ...

What is the importance of updating the uvs?

Currently, I am using the three.js editor to parse an object from JSON format. Typically, it parses materials and geometries first, followed by creating meshes. During the material parsing process, textures are also loaded. The issue at hand is that I have ...

Implementing NestJS: Integrating TypeORM Datasource without relying on class dependency injection

I have a unique situation that requires some help. Our team is in the process of integrating nestjs into our current express codebase. Previously, we were using Typeorm 0.2 and recently upgraded to 0.3. Due to the fact that we utilize functions instead of ...

Transferring data to a different module

I'm currently working on an Angular program where I am taking a user's input of a zip code and sending it to a function that then calls an API to convert it into latitude and longitude coordinates. Here is a snippet of the code: home.component.h ...

Protective layer for vertex points in three.js

I'm currently working on visualizing 3D data points using spheres in space. However, I am now looking to create a surface cover for these points. You can find the jsfiddle link for my current progress here: https://jsfiddle.net/dnprock/b9xyfno5/10/ ...

Changing namespaces or module containers that share the same name can result in a clash

Trying to reorganize some code that was mistakenly namespaced and move it to its own namespace without affecting the current functionality during the process. The original code is structured as follows: // (org) module General.Admin.Dialogs { export cl ...

Is there a version of globe (the Chrome experiment) that has been converted to the newest iteration of three.js?

Abridged tale: The code for the globe is currently based on threejs v40, while the latest version on Github is threejs r55. I'm curious if anyone with more expertise in this area has updated the globe to a newer version of three.js? Extended saga: ...

Incorporate a gltf-model into your a-frame environment using the power of three.js

Is there a way to import a gltf-model into an a-frame scene using the three.js loader directly with javascript, instead of using a-frame tags? Additionally, I need the model to include animation and be able to control this animation through three.js. You ...

Ways to implement the React.FC<props> type with flexibility for children as either a React node or a function

I'm working on a sample component that has specific requirements. import React, { FC, ReactNode, useMemo } from "react"; import PropTypes from "prop-types"; type Props = { children: ((x: number) => ReactNode) | ReactNode; }; const Comp: FC< ...

Navigating the world of Typescript: mastering union types and handling diverse attributes

I am currently working on building a function that can accept two different types of input. type InputA = { name: string content: string color: string } type InputB = { name: string content: number } type Input = InputA | InputB As I try to impleme ...

Using THREE.js to animate objects and have them settle onto a specific face

I'm currently working on adding pins to a curved map of the US, but I'm facing some challenges. Right now, I'm using mathematical calculations to determine their distance from the highest part of the curve and adjust their height accordingly ...

Having trouble with GLB file loading in three.js?

My GLB file is not displaying in my Three.js world. Despite following all the documentation and tutorials, the model is not showing up. The world loads perfectly and everything works fine, except for the model not appearing. I am on a journey to create a ...

How do I manage 'for' loops in TypeScript while using the 'import * as' syntax?

When working with TypeScript, I encountered an issue while trying to import and iterate over all modules from a file. The compiler throws an error at build time. Can anyone help me figure out the correct settings or syntax to resolve this? import * as depe ...

What are the steps for utilizing CzmlDataSource within React Resium?

Currently, I'm attempting to showcase the data from a local czml file on a map using React, Typescript, and Resium. Unfortunately, an error keeps popping up stating "This object was destroyed, i.e., destroy() was called." Can someone point out where m ...

Compatibility of Typescript with local storage

Can Typescript interact with local storage in any way? I have been setting items using the following code: localStorage.setItem('someString', JSON.stringify(MyTypescriptObject)); This method stores the object as a plain string. For example: ...