Resizing a Three.js Scene When the Browser Window Size Changes
Tags: javascript, gamedev, threejs, graphics
Published: 2020-12-07 11:33:59

---
title: Resizing a Three.js Scene When the Browser Window Size Changes
published: true
description: I'm building a social media network and collaboration tool based on mind maps, documenting my work in this series of blog posts
tags: javascript,gamedev,threejs,graphics
//cover_image: https://direct_url_to_image.jpg
series: Nuffshell Coding Diary
---

*I'm building a social media network and collaboration tool based on mind maps, documenting my work in this series of blog posts. Follow me if you're interested in what I've learned along the way about building web apps with React, Tailwind CSS, Firebase, Apollo/GraphQL, three.js and TypeScript.*

# The Problem

I've built a mind map that is rendered with [three.js](https://threejs.org). Here's what I've got so far:

{% codesandbox t6hf8 %}

When I resize the browser's viewport (using the responsive preview feature of CodeSandbox, in this case), this happens:

{% youtube rpmFW-pErn4 %}

First, I have a viewport size equivalent to a 13" MacBook Air. When I switch to various mobile device profiles, the mind map is cut off and not shown in the center of the viewport anymore.

# The Solution

I'm going to add an [window resize event](https://developer.mozilla.org/en-US/docs/Web/API/Window/resize_event) listener that executes a function when the browser window resizes. This function then updates the [HTML canvas element](https://developer.mozilla.org/en-US/docs/Glossary/Canvas) that the mind map is rendered on and tells three.js to adjust the settings of the 3D scene's camera.

# The Code

Here's my code that adds the event listener, which I've added to my module [initializeScene](https://codesandbox.io/s/drawing-a-mind-map-with-threejs-and-react-step-13-tm35p?file=/src/initializeScene.js):

```javascript
import { throttle } from 'lodash-es';
import setCanvasDimensions from './setCanvasDimensions';

const resizeUpdateInterval = 500;

window.addEventListener(
  'resize',
  throttle(
    () => {
      const width = window.innerWidth;
      const height = window.innerHeight;
      camera.aspect = width / height;
      camera.updateProjectionMatrix();
      renderer.setSize(width, height);
      setCanvasDimensions(renderer.domElement, width, height);
    },
    resizeUpdateInterval,
    { trailing: true }
  )
);
```

I'm using [throttle](https://lodash.com/docs/4.17.15#throttle) from the Lodash library to prevent the resizing to occur too often – this way, the 3D scene is updated every 500 milliseconds while the browser window is being resized.

Besides setting the size of the renderer with [setSize](https://threejs.org/docs/index.html#api/en/renderers/WebGLRenderer.setSize), I also update the width and height of the HTML canvas element that three.js renders to.

This is done in a separate function, [setCanvasDimensions](https://codesandbox.io/s/drawing-a-mind-map-with-threejs-and-react-step-13-tm35p?file=/src/setCanvasDimensions.js):

```javascript
function setCanvasDimensions(
  canvas,
  width,
  height,
  set2dTransform = false
) {
  const ratio = window.devicePixelRatio;
  canvas.width = width * ratio;
  canvas.height = height * ratio;
  canvas.style.width = `${width}px`;
  canvas.style.height = `${height}px`;
  if (set2dTransform) {
    canvas.getContext('2d').setTransform(ratio, 0, 0, ratio, 0, 0);
  }
}
```

I'm using a trick here to make sure the canvas looks good on devices with a high pixel ratio, such as iPhones with Retina displays ([see my previous post with details on this](https://dev.to/pahund/how-to-fix-blurry-text-on-html-canvases-on-mobile-phones-3iep)).

When I resize the window now, it works as one would expect:

{% youtube 4XDPr0rJL2c %}

Here's the whole project if you want to try it out:

{% codesandbox tm35p %}

# To Be Continued…

I'm planning to turn my mind map into a social media network and collaboration tool and will continue to blog about my progress in follow-up articles. Stay tuned!