Why does Three.js change the innerWidth and innerHeight of a div on its own after being set with the width and height of a plane?

Greetings, I have a question.

In my attempt to adjust the innerWidth and innerHeight of the div container which houses a canvas element, I am using the code snippet below. The crucial part is the loader.load function that gets executed upon completion of loading the plane on the page.

// This class manages the loading process and canvas for an nrrd file
// Utilizing prototype-based programming: https://javascript.info/class

InitCanvas = function (IdDiv, Filename) {
    this.IdDiv = IdDiv;
    this.Filename = Filename
}

InitCanvas.prototype = {

constructor: InitCanvas,

init: function () {

this.container = document.getElementById(this.IdDiv);

debugger;
this.container.innerHeight = 600;
this.container.innerWidth = 800;

// These lines should be modified to enhance the image position    
this.camera = new THREE.PerspectiveCamera(60, this.container.innerWidth / this.container.innerHeight, 0.01, 1e10);
this.camera.position.z = 300;

let scene = new THREE.Scene();
scene.add(this.camera);

// Light

let dirLight = new THREE.DirectionalLight(0xffffff);
dirLight.position.set(200, 200, 1000).normalize();

this.camera.add(dirLight);
this.camera.add(dirLight.target);

// Read file

let loader = new THREE.NRRDLoader();
loader.load(this.Filename, function (volume) {

// Z-plane
let sliceZ = volume.extractSlice('z', Math.floor(volume.RASDimensions[2] / 4));

debugger;
this.container.innerWidth = sliceZ.iLength;
this.container.innerHeight = sliceZ.jLength;

sliceZ.mesh.material.color.setRGB(0,1,1);

console.log('Our slice is: ', sliceZ);

scene.add(sliceZ.mesh);
this.scene = scene;

// Renderer

this.renderer = new THREE.WebGLRenderer({alpha: true});
this.renderer.setPixelRatio(this.container.devicePixelRatio);
debugger;
this.container.appendChild(this.renderer.domElement);
}.bind(this));
},

animate: function () {
this.renderer.render(this.scene, this.camera);
}

}

As you can observe from the code, I'm binding 'this' within the loader.load asynchronous call to access the 'container' property in the InitCanvas class.

After the completion of loading the plane, we retrieve the width and height with these lines:

this.container.innerWidth = sliceZ.iLength;
this.container.innerHeight = sliceZ.jLength;

I noticed through the web debugger that the width and height of the loaded plane are indeed reflected in the container inside the div:

https://i.sstatic.net/T27Yb.png

The values shown indicate that this.container.innerWidth has been updated to 3128 and this.container.innerHeight to 1760.

However, after rendering the plane, the container div displays dimensions of 300x150 as depicted here:

https://i.sstatic.net/UKu6u.png

How is this discrepancy possible?

Moreover, why does our web console throw this error:

Uncaught TypeError: Cannot read property 'render' of undefined
at InitCanvas.animate (InitCanvas.js:79)
at animate (logic.js:63)

I presume this error occurs because we don't have access to this.renderer within the loader.load function due to the bind(this) technique used. However, in the animate() function, the scope of the InitCanvas class is lost.

What could be done to rectify this issue?

Thank you for your assistance!

Here is additional relevant code:

logic.js

// Code logic goes here

index.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>Prototype: three.js without react.js</title>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
        <link rel="stylesheet" href="css/styles.css">

        <!-- Load necessary scripts -->

    </head>

    <body>
        <div id="info">
            <h1>Prototype: three.js without react.js</h1> 
        </div>

        <!-- Two canvas elements -->
        <div class="row">
            <div class="column" id="original">
            </div>

            <div class="column" id="segment">

            </div>
          </div> 

        <script src="js/logic.js"></script>

    </body>
</html>

styles.css

body {
    font-family: Monospace;
    margin: 0px;
    overflow: hidden;
}

#info {
    color: rgb(137, 145, 192);
    position: absolute;
    top: 10px;
    width: 100%;
    text-align: center;
    z-index: 5;
    display:block;
}

.column {
    float: left;
    width: 50%;
}

/* Clear floats after the columns */
.row:after {
    content: "";
    display: table;
    clear: both;
}

canvas {
    width: 200px;
    height: 200px;
    margin: 100px;
    padding: 0px;
    position: static; /* fixed or static */
    top: 100px;
    left: 100px;
}

Answer №1

Merely adjusting the container's size will not adjust the renderer's size. You must use renderer.setSize(width, height); to alter the canvas' dimensions accordingly.

Moreover, the devicePixelRatio property belongs to the window object. Trying to access it via this.container.devicePixelRatio will result in a return value of undefined.

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

I am trying to access a value saved in a service in Angular 8 component and use it in other services. Can anyone help

Setting a value through a component export class UniqueComponent { constructor(service:UniqueService){ } count =0 ; onRefresh(){ this.service.count = 1; } } Using the value in the service UniqueService{ count:any; doSomething(){ //using count ...

Issue with Typescript not recognizing default properties on components

Can someone help me troubleshoot the issue I'm encountering in this code snippet: export type PackageLanguage = "de" | "en"; export interface ICookieConsentProps { language?: PackageLanguage ; } function CookieConsent({ langua ...

jQuery Datatables causing hyperlinks to malfunction on webpage

After implementing jQuery datatables on this example using a PHP serverside processing file pulling data from MySQL, the Sign-in button used to work but now it just reloads the same index page. Manually typing in the address linked to the Sign In page work ...

Adding animation effects using CSS and/or jQuery

Are there any Jquery plugins or CSS codes available to achieve similar effects as seen on the following pages and , without utilizing webGL?... ...

Search for every div element and locate the ul element within it. Calculate the total number of table rows present in the ul element. Add this

There is a list on my website with a sublist called .cart-items. This sublist contains a table with multiple rows. My goal is to iterate through each .cart-select item and count the number of tr elements within the cart-items. The count should then be disp ...

When the browser is launched, the Three JS scene initially appears too small before being resized upon window.onload

Recently, I started diving into the world of WebGL with a basic goal in mind: whenever I open my index.html file, I want the rendered scene to perfectly fit the window size without any initial hiccups. But, every time I run the code I adapted from WebGL tu ...

Why is it important to have specific property names?

Here is some code and HTML for triggering a radio button. It seems to work fine without any issues, but I'm wondering if the presence of a name property is necessary. When I remove the name property, it stops working. Can someone explain why? <inp ...

Error message in MS Edge API: 'browser has not been defined'

I'm currently in the process of developing an extension for the new Microsoft Edge browser. Upon loading the unpacked extension, I encountered the following error: Uncaught ReferenceError: browser is not defined According to the Microsoft Edge docu ...

Learn how to utilize JavaScript produced by the `webpack output library` in a `nodejs` application

I'm currently utilizing webpack to bundle my JavaScript into a library that serves two purposes: one for browser usage and the other for integration into Node.js applications. Below is a snippet of my webpack configuration: output: { filename: ...

Maximizing the Width of a Background Image in Wordpress Elementor for a Full Screen Effect

UPDATE: Issue Resolved! See the comments for details. Thanks to the helpful Dev! I'm facing a challenge with my website's homepage design. I'm trying to incorporate a background image that spans the full width of the screen. My website is b ...

Display the iframe website without it being visible to the user

Is there a way to load a separate website, such as a Wikipedia article, in an iframe on a webpage without freezing up the whole page when it becomes visible after clicking a "show" button? And if not, how can we display a loading gif while the iframe is ...

Using Javascript to implement a min-width media query

I'm currently facing an issue with my website () where the media query (min-width) is not effectively removing a JavaScript code within a specific div. The HTML structure in question is as follows: <div id="advertisementslot1"> <script lang ...

Is there a way to automatically fill in a MUI textfield in a React Hook form with data retrieved from Firestore?

Utilizing React Hook Forms alongside MUI TextField components has been a productive challenge for me. I've been able to successfully fetch data from Firestore and aim to prefill the form with this retrieved information. Although I am employing useFor ...

Add a value in front of switchMap along with a Promise

Whenever a new value is emitted by this.selectedLanguage$, I need to emit a value that is calculated asynchronously. My current approach to this requirement involves the following code: public readonly languageCategories$ = this.selectedLanguage$.pipe( ...

Are there any JavaScript libraries available that can mimic SQLite using localStorage?

My current application makes use of SQLite for storage, but I am looking to switch it up to make it compatible with Firefox and other browsers. I've been considering localStorage as an option. However, I've noticed that localStorage lacks some o ...

Deleting a row from a table in AngularJS can be accomplished by following these steps

I am having trouble with deleting rows from a table using angularjs. When I try to delete a row, it ends up deleting the previous row instead of the correct one. How can I fix this issue? Please check out the working DEMO Here is the code snippet: < ...

Incorporating an additional table dynamically based on height considerations – can you provide visuals as guidance?

The visual representation of my question far surpasses my verbal explanation. My intention is to insert a new table once the height of the previous table exceeds a specific HEIGHT limit, not a certain number of rows. This project does not involve creat ...

Tips for executing a function in jQuery when a Pop up appears

I am currently utilizing the AjaxToolKit:ModelPopUpExtender to generate a popup within an asp.net application. At first, the asp:Panel (which holds the content of the popup) is set as <asp:Panel ID="PanlUpdate" runat="server" CssClass="Popup" align="c ...

What is the best way to prevent a draggable div from moving past the edge of the viewport?

My situation involves a draggable div that functions as a popup window when a specific button is clicked. However, I noticed that dragging the div to the end of the viewport allows me to drag it out of the visible area, causing the body of the page to expa ...

I recently attempted a meyers reset and now I'm struggling to get my unordered list to display in a horizontal layout

Check out my code snippet below: .navbar-container { width:100%; display:inline-block; } ul { list-style-type: none; display: inline; } <div class="navbar-container"> <ul> <li><a href="gmail.com">Gmail</a>& ...