Ensuring consistent geometry size regardless of renderer size is crucial - Plane resizing based on screen dimensions

https://i.sstatic.net/CwUxD.gif

Here is a codepen showcasing the issue along with a GIF illustrating the confusion.

Codepen: https://codepen.io/carelesscourage/pen/bGMWjNg

My expectation

I desire the plane to maintain the same size regardless of screen size.

//WebGl renderer
function useWebGl(root = document.body) {
  const renderer = new THREE.WebGLRenderer({ alpha: true })
  renderer.setClearColor( 0x009900, 1 )
  renderWindow(renderer)
  root.appendChild( renderer.domElement )
  onResize(() => renderWindow(renderer))
  return { WebGl: renderer }
}

function renderWindow(renderer) {
  const { height, width } = windowDimensions()
  renderer.setSize( width / 2, height / 2 )
}


//ThreeJS Engine
function initEngine() {
  const scene = new THREE.Scene()
  const camera = getCamera()
  
  const { WebGl } = useWebGl()
  function everyFrame(callback = () => {}) {
    callback()
    WebGl.render( scene, camera )
    requestAnimationFrame(() => everyFrame(callback))
  }

  return {scene, everyFrame}
}

Everything below this line stems from the original post. I have addressed some issues and reduced the codepen to focus solely on the problem at hand. The text above this line highlights the specific issue, while the following content is retained for reference:

https://i.sstatic.net/qakGW.gif

Context

My ultimate objective is to create a plane in three.js that aligns with and sticks to an HTML element. At this stage, I am seeking assistance on how to ensure the size and position of the plane remain consistent across different screen sizes, particularly focusing on the size aspect.

Issue: I expect the plane to remain at a fixed distance from the left edge on all screen sizes. However, the plane currently shifts unpredictably in both position and size with varying screen sizes. Even when setting a static size for the plane, it behaves erratically across different screen dimensions. Despite tying the plane size to the html image size in the code, the plane continues to exhibit random changes in size.

Regarding position: The code instructs the plane to move to the top left corner of the canvas and then offset back to match the position of the HTML element relative to the top right of the screen. While this works in fullscreen desktop view, resizing the window results in inaccurate offsets and size fluctuations. The plane occasionally changes size entirely.

My expectation

I anticipated the plane to maintain a consistent size irrespective of screen size.

My best guess

The issue seems unrelated to how the plane's position is offset, as even disabling that code does not resolve the size inconsistencies. Given that the problem persists when all position and size-related code is removed, I suspect the camera handling may be the root cause. Although I utilize an orthographic camera, similar issues arise with a perspective camera.

If my assumption is correct, the problem likely lies in this section of the code:

function windowDimensions() {
  const height = window.innerHeight
  const width = window.innerWidth
  const aspect = width / height;
  return { height, width, aspect}
}

function cameraDimensions(aspect, viewSize = 1000) {
  const caps = viewSize / 2
  const sides = aspect*viewSize / 2
  return { caps, sides }
}

function getCamera() {
  const { aspect } = windowDimensions()
  const { caps, sides } = cameraDimensions(aspect)

  const camera = new THREE.OrthographicCamera(
    -sides, sides,
    caps, -caps,
    -1000, 1000
  )

  window.addEventListener('resize', () => {
    updateCamera(camera)
  })
  
  camera.position.z = 500;
  return camera
}

function updateCamera(camera) {
  const { aspect } = windowDimensions()
  const { caps, sides } = cameraDimensions(aspect)
  camera.left = -sides,
  camera.right = sides,
  camera.top = caps,
  camera.bottom = -caps,
  camera.updateProjectionMatrix();
}

Answer №1

After some investigation, I was able to identify the root cause of the issue. I will explain the solution I implemented here for the benefit of future visitors. The main problem lies within this piece of code:

function cameraDimensions(aspect, viewSize = 1000) {
  const caps = viewSize / 2
  const sides = aspect*viewSize / 2
  return { caps, sides }
}

export function getCamera() {
  const { aspect } = windowDimensions()
  const { caps, sides } = cameraDimensions(aspect)

  //const camera = new THREE.PerspectiveCamera( 75, aspect, 0.1, 1000 )
  const camera = new THREE.OrthographicCamera(
    -sides, sides,
    caps, -caps,
    -1000, 1000
  )

  window.addEventListener('resize', () => {
    updateCamera(camera)
  })
  
  camera.position.z = 500;
  return camera
}

Specifically, the issue resides in the calculation of top, bottom, and sides for the OrthographicCamera within the mentioned function.

function cameraDimensions(aspect, viewSize = 1000) {
  const caps = viewSize / 2
  const sides = aspect*viewSize / 2
  return { caps, sides }
}

The current method of determining the camera dimensions works well for scaling geometry based on the render size. However, for my specific requirements, I found that adjusting the values based on window size was more suitable:

const cameraDimensions = (aspect, viewSize = 1000) => ({
  caps: window.innerHeight / 2,
  sides: window.innerWidth / 2
})

I am grateful to Darkmatter from the three.js discord community for providing a helpful codepen that guided me towards the solution. Here is the codepen link for reference.

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

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

Verify the text file for any data, and if it contains any, display it on the web browser using JavaScript

I have a program in C that works with a temperature sensor. It creates a file to store the temperature and indicates whether it falls within specific values. I want to display this data on a web browser and update it every 5 minutes. I'm looking for ...

Exploring ways to access global window variables in React using JavaScript

I've been following the discussion on how to transfer variables from JavaScript to ReactJS. Here is my array of objects in JavaScript: window.dataArr = []; function makeJsObj(descr, currDate, done) { var data = {}; console.log(descr ...

Differences between Sequelize classMethods and instanceMethods

Embarking on my Node journey, I've decided to explore Sequelize. Initially, my focus was on understanding the following code: 'use strict'; var crypto = require('crypto'); module.exports = function(sequelize, DataTypes) { var U ...

Determine whether the object is facing the specified position

I'm attempting to verify whether an object (this.target) is facing towards a particular position (newPosition). Here's what I currently have: new THREE.Matrix4().lookAt( newPosition, this.target.position, this.target.up ) == this.target.matrix ...

Having difficulty accessing certain code in TypeScript TS

Struggling with a TypeScript if else code that is causing errors when trying to access it. The specific error message being displayed is: "Cannot read properties of undefined (reading 'setNewsProvider')" Code Snippet if (this.newsShow != ...

Is there a way to execute v-for once the created() lifecycle hook has finished running?

In my current project, I am faced with the challenge of including avatars in notifications. Despite my efforts, I have not been able to solve this issue independently. The Vue.js template below demonstrates how I have attempted to add avatars to each notif ...

Instructions for utilizing a non-string reference without triggering flow errors

I've noticed that string refs are considered legacy in React. You can read more about it here: https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-string-refs.md However, I am encountering a flow error in my component and I&apo ...

When implementing Firebase Cloud Messaging with React, the token generated by firebase.messaging().getToken() will vary with every refresh

I'm working on a React web app using Gatsby and I want to integrate push notifications through FCM. My firebase-messaging-sw.js service worker is set up, and I'm trying to retrieve a token using the following method in my app: messaging .req ...

Can you explain the distinction between the onclick(function(){}) and on('click',function(){}) functions in jQuery?

My goal is to dynamically load pages into a specific div using ajax. Here's my HTML code: <ul id="nav" class="nav" style="font-size:12px;"> <li><a href="#" id="m_blink">Tab1</a></li> <li><a href="#" id= ...

Is it possible to drag the div container in HTML to resize its width from both left to right and right to left?

After posing my initial inquiry, I have devised a resizing function that allows for the expansion of a div's width. When pulling the right edge of the div to resize its width from left to right, is it possible to adjust the direction or how to resize ...

What is causing the click event handler to only function on the initial page?

Within my code for the "fnInitComplete" : function(oSettings, json), I am utilizing a selector like $('[id^=f_]').each(function (). The data for Datatables is retrieved server-side and "bProcessing":true I am aware that my selectors are only ef ...

Utilize SVGs efficiently by loading them once and reusing them

Is it possible to use the same SVG element twice on a web page without having to load it again? I am changing the CSS of the SVG using JavaScript, so I believe the SVG must be directly embedded in the HTML rather than included as an object. Both instance ...

Showing information from a database while incorporating line breaks with the help of nl2br

Having trouble with the previous question, so I'll provide more detail here. Below is my index.php file where I explain the method used to save data to a database. <html> <head> <script> function updategroup() { var update_c ...

Optimal method for retrieving data from a JSON object using the object's ID with a map

Can you teach me how to locate a json object in JavaScript? Here is a sample Json: { "Employees" : [ { "userId":"rirani", "jobTitleName":"Developer", "preferredFullName":"Romin Irani", "employeeCode":"E1", "region":"CA", "phoneNumber":"408-1234567", " ...

The AJAX request for JSON data is functioning correctly in Firefox, but is experiencing compatibility issues with other web browsers

I recently completed a PHP page that generates a valid JSON document. The jQuery code used to fetch and display the data is quite straightforward: $.ajax({ url: "http://localhost:8888/rkm/json-jc", dataType: "json", success: function(data) { ...

Is it true that Safari restricts AJAX Requests following a form submission?

I've developed a JavaScript-based upload progress meter that utilizes the standard multipart submit method instead of submitting files in an iframe. The process involves sending AJAX requests during submission to retrieve the percentage complete of th ...

The functions.php file is failing to execute the JavaScript files located in the js folder

I've been attempting to incorporate a JS accordion into my Wordpress blog, but I seem to be encountering issues with the accordion.js file not loading through the functions.php file. Interestingly enough, when I manually add the js code in the header ...

Importing Laravel select2 library is necessary for enhancing user experience and improving

I've been attempting to incorporate select2 into my project without success. Every time I try these two methods, I always receive an error saying $('#state').select2 is not a function. However, when I include select2 in a standard <scrip ...

Launching a URL in a pop-up window with customized title and address bar

I am seeking to implement a feature similar to the following: <a href="post/23">post 23</a> When a user clicks on this element, I want a popup div to fade in and load the HTML from page post/23 into it. Additionally, I would like the title an ...

Determining the live total number of Protovis Sparkbar instances

I am currently working on a project where I need to show the ratings and corresponding dates (in string format) from a JSON file in tipsy tooltips. The data consists of a list of dates and ratings. For example: var data = [{"dates":["2010-07-01","2010-07 ...