Creating visualizations using Three.js in a vscode extension

I am in the process of developing a vscode extension that aims to visualize 3D meshes. Here is the function responsible for retrieving the HTML content:

function getWebviewContent(context: vscode.ExtensionContext, panel: vscode.WebviewPanel) {
      const threejs =  vscode.Uri.file(context.extensionPath+"/js/three.js");  
      const threejsUri = panel.webview.asWebviewUri(threejs);
      const geometryjs =  vscode.Uri.file(context.extensionPath+"/js/geometry.js");  
      const geometryjsUri = panel.webview.asWebviewUri(geometryjs);
      return `
      <!DOCTYPE html>
      <html>
        <head>
          <meta charset="utf-8">
          <title>My first three.js app</title>
          <style>
            body { margin: 0; }
          </style>
        </head>
        <body>
          <script src=${threejsUri}></script>
          <script src=${geometryjsUri}></script>
        </body>
      </html>
      `
}

When using my geometry.js, everything displays correctly:

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );

const renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );

const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
const cube = new THREE.Mesh( geometry, material );
scene.add( cube );

camera.position.z = 5;

function animate() {
    requestAnimationFrame( animate );

    cube.rotation.x += 0.01;
    cube.rotation.y += 0.01;

    renderer.render( scene, camera );
};
animate();

However, when I encapsulate the code into a class like so:

import { Scene, PerspectiveCamera, WebGLRenderer, BoxGeometry, MeshBasicMaterial, Mesh, requestAnimationFrame } from 'three';
class Viewer {
    constructor() {
        // Code snippet here
    }
    
    animate() {
        // Animation logic here
    }
}

let viewer = new Viewer();
viewer.animate();

The rendered page remains empty. What might be causing this issue? Since I rely on an external rendering package which utilizes classes, I need to ensure correct implementation and usage of classes.

Note: I have attempted switching geometry.js to typescript, but encountered no success

// TypeScript code block here

Additional note: Curiously, the following approach seems to work:

// A different code structure that functions properly

This raises the question as to why the animate() function needs to be nested inside init(). In a class setup, shouldn't member components use this instead?

Further Edit:

// Latest modifications to the class structure

Answer №1

requestAnimationFrame attempts to execute the provided function within the scope of the window object (this === window).

When you organize your code in a functional manner (using original and edit 2 methods), some objects are encapsulated in a way that allows access inside the animate function. However, if you use a class and requestAnimationFrame invokes this.animate, it may initially work but on subsequent calls, your this will refer to window leading to unexpected behavior.

To resolve this issue, one common approach is to bind the function to a specific context to prevent unintentional overrides. Alternatively, you can directly call the function while specifying the desired context.

Applying function binding

class MyClass{
  constructor(){
    this.boundAnimate = this.animate.bind(this);
  }

  animate(){
    requestAnimationFrame(this.boundAnimate);
  }
};

Utilizing call

class MyClass{
  animate(){
    window.prototype.requestAnimationFrame.call(this, this.animate);
  }
};

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

Retrieve information and update state right before component display in React Native

Consider this scenario: I have a modal that displays data from its state, which is an array. The state is set in the componentDidMount() function as recommended in the documentation. My goal is to display updated data every time the modal opens. I was able ...

Unable to obtain the vertices of the extremities due to the absence of labels on AxisHelper

My goal is to add labels on AxisHelper in Three.js that rotate along with it. I came across a helpful code snippet from this source: // Axes axes2 = new THREE.AxisHelper(70); // Axes labels addLabelAxes(); // Add axes to zoomScene zoomScene.add(axes2); ...

Utilizing lodash to extract arrays from objects within a larger array

_lodash Here is the structure of my tickerTagObject array: It consists of objects, with each containing another object along with an additional array I have successfully extracted tickers using the following code snippet: var tickerObjs = _(tickerTagOb ...

Leveraging PHP for populating JavaScript variables

I am currently working on populating a Drop-Down menu from a csv file stored on a network share. So far, I have successfully managed to populate the options when the file is in the wwwroot folder. However, I am now encountering an issue with referencing a ...

Can a formula be derived to determine the minimum length needed for achieving distinctiveness within a given set?

I am interested in calculating the shortest sub-string length needed to achieve complete uniqueness. Let's consider a list of 32 character UUIDs, and my goal is to shorten them to the minimum length necessary to ensure uniqueness within the set. For ...

Knockout Observable Array causing UI to freeze and not refresh properly

I recently started using knockout and am exploring the use of observable arrays to track changes from the UI. The initial data is loaded into the array and I'm attempting to dynamically add new objects to the array from another screen. Although I hav ...

Axios appends square brackets at the end of the parameter name

Utilizing vuejs in combination with axios and a Django server presents a challenge. The server requires parameters to be passed as travelers, but when using axios to send this data, it appends [] at the end resulting in travelers[]. Is there a way to prev ...

Tips for sorting through an array of objects in JavaScript?

I'm currently working on filtering my array within an Angular 4 component. The array includes a property that is also an array: export const data = [ { "number": "1", "lines": [ "aaaaabbbb bbbbb ccccc ddddd", "aaaaabbbb bbbbb cc ...

Utilize a personalized useFetch hook in React.js to transmit a POST request and obtain a response

I recently came across a great resource on this website that provided the logic for a useFetch hook. My goal is simple - I want to send a post request and then map the response into a specific type. While this seems like it should be straightforward, I&apo ...

The challenge of executing JavaScript in the correct order

I am facing an issue where 5 always prints before 4 in my code snippet below. I expected the callback to postUsers within a return statement from matchAgainstAD to wait for the completion of the for loop and ad lookup before returning. What is the simple ...

Creating clickable div elements within a loop

In the .JS file I have the function below (which I later call in an HTML file): function writeDiv(){ x = 1 myArray.forEach(item => { htmlText += '<div class="divsArray">'; htmlText += '<h5> Value of X ...

The NPM version needs to be updated as it is outdated

Struggling with a dilemma here. My Laravel project is quite dated, and I'm unable to execute npm run dev. Let's take a look at some code: php artisan laravel --version: Laravel Framework 5.8.38 node --version: v16.16.0 This is the current Node v ...

Optimizing NodeJS for scheduling and sending bulk text messages based on MongoDB data

I am currently developing an application that relies on MongoDB database entries to send text messages through AWS. The information stored in the database includes the message content, phone number, and scheduled time for sending the message. As of now, ...

Develop an interactive React sidebar with changing elements

I'm in the process of developing a sidebar for a project, with the goal of making it similar to tools like Confluence. This means that we need the ability to rearrange documents and create subdirectory structures by simply moving the documents, with ...

Steps to successfully trigger the onchange event in JavaScript from within a modal dialog box

In my Asp.net MVC project, I am facing an issue with the Change event of the "PersonNature" Combobox in my view index. The combobox is located within the PartialView _Person and is rendered inside the PartialView Create. When a PersonNature is selected, it ...

Modifying the $locale setting in ui-router

My Goal and Approach Within our AngularJS application, we utilize angular-ui-bootstrap for datepickers. Our aim is to localize the datepickers based on the user's locale. However, dynamically changing the locale in AngularJS poses a challenge due to ...

Issue with TypeScript problemMatcher "$tsc-watch" not actively monitoring files in VSCode

I'm attempting to avoid the necessity of using watch: true in my tsconfig.json setup. Despite utilizing VSCode's tasks with the default problem matcher $tsc-watch, I am encountering an issue where tsc is not running in watch mode during the buil ...

Choose a radio button from a React Native FlatList

I am new to React Native and I'm working with the expo-radio-button component. However, I'm facing an issue where I can't seem to select only one radio button at a time in a flatlist. When I try to select a single button, it ends up select ...

JavaScript validation is failing, yet the form is still getting submitted

I'm facing an issue with my JS validation. It seems to be working fine, checking for a valid number that isn't zero, but the form is still submitting. I've searched for a solution to this problem, but none seem to work for me. Any suggestion ...

Encountering an error message stating, "Unable to interpret property

I need to retrieve specific information import React,{Component} from 'react'; import axios from 'axios'; import CoinsConvert from '../data/data' import '../style/bootstrap.min.css'; class BoxInfo extends Component ...