How do I scale a 2D React image to match Three.js Object on window resize?

Been stuck on this problem for the past 3 days so would appreciate any help!


I’m trying to seamlessly transition between a Three.js particle animation that forms my logo in its final position and a 2D React image of the same logo. The goal is to have the React image consistently match the size of the particle logo, even when the browser window is resized.


  • I have a three.js animation that ends on particles in the arrangement / position, of my logo.
  • My camera is positioned at: 0,0,80 while the bounding box (and also the particle logo) is at 0,0,0.
  • The 2D React image of the logo needs to dynamically scale to match the size of this particle logo.


  1. Computing a bounding box for the particle logo at the same coordinates (0,0,0) and then getting the bounding box size [logoBoundingBox.getSize(new THREE.Vector3());] in world units.
  2. Attempt to convert the world units to pixels using the following calculations:
const vFov = (camera.fov * Math.PI) / 180;
const height = 2 * Math.tan(vFov / 2) * distance;
const aspect = window.innerWidth / window.innerHeight;
const width = height * aspect;

// Calculate the size of the bounding box in pixels
const widthInPixels = window.innerWidth * ((1 / width) * size.x);
const heightInPixels = window.innerHeight * ((1 / height ) * size.y);

resolveSizePromise({ widthInPixels, heightInPixels });

This outputs a larger react image.

Alternatively, I tried this to get the proportion of the visible width the bounding box occupies and then using that factor to get the same proportion of the window’ inner width to size the react image:

var VFov = camera.fov * Math.PI / 180; 
var Height = 2 * Math.tan(sceneVFov / 2) * (camera.position.z - center.z);
var Aspect = window.innerWidth / window.innerHeight;
var Width = Height * Aspect;
const scaleFactor = size.x / Width; 
// in the react file i then multiplied the window's inner width by the scaleFactor to try and get the react image to match the bounding box in size as such...
logoWidth: window.innerWidth * scaleFactor

However this outputs a react image larger than the boundingBox.

If you stop the render loop after the logo animation is finished - you get an image. WebGL renders to canvas, which is just a fancy img element.

Moreover, if for some reason you really really want img element instead of canvas - you can just finalise the animation, stop at the last frame, grab pixels data from the render target and transform them into a Blob. Then you can use that blob as base64 source for an img src attribute. But that’ll kinda be equivalent to stopping the render loop and not doing anything besides that.

Thank you so much. I will give this a shot

Not getting this to work as intended unfortunately. I need the logo as an img element as I will be building a react web app on top of the threeJS animation. The animation ends on the particles. I could load in the 2d logo in three.js (handle the transition between the particle logo and actual logo in my three.js code), then grab the pixel data, and import that into react file and use as img src. However there must be a computationally easier method, given the requirements?