# Functions to calculate the visible width / height at a given z-depth from a perspective camera

**URL:** <https://discourse.threejs.org/t/functions-to-calculate-the-visible-width-height-at-a-given-z-depth-from-a-perspective-camera/269>\
**Category:** Resources\
**Tags:** perspective-camera, camera\
**Created:** [April 28, 2017, 10:02am UTC](https://discourse.threejs.org/t/functions-to-calculate-the-visible-width-height-at-a-given-z-depth-from-a-perspective-camera/269 "2017-04-28T10:02:14Z")\
**Posts on this page:** 12\
**Page:** 2

<div class="post-metadata">

**Author:** ![trusktr](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/trusktr/32/13726_2.png) [@trusktr](https://discourse.threejs.org/u/trusktr)\
**Post date:** [April 22, 2020, 5:58am UTC](https://discourse.threejs.org/t/functions-to-calculate-the-visible-width-height-at-a-given-z-depth-from-a-perspective-camera/269/23 "2020-04-22T05:58:30Z")

</div>

Looks like some of the above codepens I posted broke. I need to update them. Nowadays I make sure to use versioned URLs to make sure demos don’t break.

---

<div class="post-metadata">

**Author:** ![trusktr](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/trusktr/32/13726_2.png) [@trusktr](https://discourse.threejs.org/u/trusktr)\
**Post date:** [May 18, 2020, 8:47pm UTC](https://discourse.threejs.org/t/functions-to-calculate-the-visible-width-height-at-a-given-z-depth-from-a-perspective-camera/269/24 "2020-05-18T20:47:22Z")

</div>

I updated all the above pens so they work now. I used specific versions in the code to make sure they rely on the proper versions, like this:

```auto
import * as THREE from 'https://unpkg.com/three@0.116.1/build/three.module.js'
import {OrbitControls} from 'https://unpkg.com/three@0.116.1/examples/jsm/controls/OrbitControls.js'

```

@looeee Do you mind updating your two codepens above? These are your pens updated to use specific versions:

- [https://codepen.io/trusktr/pen/8cffa33f19b02f5ea5b0ab1bd64122e0?editors=0110](https://codepen.io/trusktr/pen/8cffa33f19b02f5ea5b0ab1bd64122e0?editors=0110)
- [https://codepen.io/trusktr/pen/6048a9dc716fd1aa69c06c7921d4146a?editors=0110](https://codepen.io/trusktr/pen/6048a9dc716fd1aa69c06c7921d4146a?editors=0110)

---

<div class="post-metadata">

**Author:** ![mohtasimtamjeed](https://avatars.discourse-cdn.com/v4/letter/m/a3d4f5/32.png) [@mohtasimtamjeed](https://discourse.threejs.org/u/mohtasimtamjeed)\
**Post date:** [May 28, 2020, 1:39am UTC](https://discourse.threejs.org/t/functions-to-calculate-the-visible-width-height-at-a-given-z-depth-from-a-perspective-camera/269/25 "2020-05-28T01:39:47Z")

</div>

Hi  
I am new to 3d graphics/rendering so apologies in advance  
Do you think this is possible for orthographic camera

---

<div class="post-metadata">

**Author:** ![KyleCe](https://avatars.discourse-cdn.com/v4/letter/k/65b543/32.png) [@KyleCe](https://discourse.threejs.org/u/KyleCe)\
**Post date:** [July 13, 2020, 9:59am UTC](https://discourse.threejs.org/t/functions-to-calculate-the-visible-width-height-at-a-given-z-depth-from-a-perspective-camera/269/26 "2020-07-13T09:59:39Z")

</div>

This fits good on Mobile device, both Android WebView and iOS webkit. You definitely knows the logic behind it. Good job, man.

---

<div class="post-metadata">

**Author:** ![trusktr](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/trusktr/32/13726_2.png) [@trusktr](https://discourse.threejs.org/u/trusktr)\
**Post date:** [July 14, 2020, 3:09am UTC](https://discourse.threejs.org/t/functions-to-calculate-the-visible-width-height-at-a-given-z-depth-from-a-perspective-camera/269/27 "2020-07-14T03:09:18Z")

</div>

With an OrthographicCamera, objects don’t get smaller when they go further away from the camera so this trick doesn’t work.

What you would need to do is make sure the ortho camera box dimensions are the size of the object, or scale the object to fit the size of the camera box. This is easier than the above with perspective camera, you just need a multiplier.

For example, if your ortho cam width and height are both 10, and the object width/height is 5, then you need to scale the object by 2 so it fits on the screen (or reduce the camera width/height to 5). Simple as that.

---

<div class="post-metadata">

**Author:** ![trusktr](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/trusktr/32/13726_2.png) [@trusktr](https://discourse.threejs.org/u/trusktr)\
**Post date:** [July 14, 2020, 3:11am UTC](https://discourse.threejs.org/t/functions-to-calculate-the-visible-width-height-at-a-given-z-depth-from-a-perspective-camera/269/28 "2020-07-14T03:11:43Z")

</div>

In case it helps anyone, here’s how to fit an object (most likely a flat plane) on the screen so that it “fits” depending on aspect ratio. For example, if we have an object taller than it is wide we want the Y dimension (the tall dimension) to fit within the view, but if the object is wider than it is tall we want the X dimension (the width dimension) to fit within view.

The following `distanceToFitObjectToView` function will tell you at what distance to place the object so that it fits within view regardless which dimension is bigger:

(The code has TypeScript type annotations, but you can remove them, f.e. the `: number` stuff)

> ( **Note, angles are in _radians_!** )

```javascript
/**
 * Convert vertical field of view to horizontal field of view, given an aspect
 * ratio. See https://arstechnica.com/civis/viewtopic.php?f=6&t=37447
 *
 * @param vfov - The vertical field of view.
 * @param aspect - The camera aspect ratio, which is generally width/height of the viewport.
 * @returns - The horizontal field of view.
 */
function vfovToHfov(vfov: number, aspect: number): number {
  const {tan, atan} = Math
  return atan(aspect * tan(vfov / 2)) * 2
}

/**
 * Get the distance from the camera to fit an object in view by either its
 * horizontal or its vertical dimension.
 *
 * @param size - This should be the width or height of the object to fit.
 * @param fov - If `size` is the object's width, `fov` should be the horizontal
 * field of view of the view camera. If `size` is the object's height, then
 * `fov` should be the view camera's vertical field of view.
 * @returns - The distance from the camera so that the object will fit from
 * edge to edge of the viewport.
 */
function _distanceToFitObjectInView(size: number, fov: number): number {
  const {tan} = Math
  return size / (2 * tan(fov / 2))
}

function distanceToFitObjectToView(
  cameraAspect: number,
  cameraVFov: number,
  objWidth: number,
  objHeight: number
): number {
  const objAspect = objWidth / objHeight
  const cameraHFov = vfovToHfov(cameraVFov, cameraAspect)

  let distance: number = 0

  if (objAspect > cameraAspect) {
    distance = _distanceToFitObjectInView(objHeight, cameraVFov)
  } else if (objAspect <= cameraAspect) {
    distance = _distanceToFitObjectInView(objWidth, cameraHFov)
  }

  return distance
}

```

# Demo

Here’s a live example showing the concepts put together. Open it in new tab, try resizing vertically and horizontally, and try both “contain” and “cover” modes in the code (like [CSS object-fit](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit)):

[https://codepen.io/trusktr/pen/jOQZZdZ?editors=1000](https://codepen.io/trusktr/pen/jOQZZdZ?editors=1000)

---

<div class="post-metadata">

**Author:** ![trusktr](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/trusktr/32/13726_2.png) [@trusktr](https://discourse.threejs.org/u/trusktr)\
**Post date:** [July 14, 2020, 5:36pm UTC](https://discourse.threejs.org/t/functions-to-calculate-the-visible-width-height-at-a-given-z-depth-from-a-perspective-camera/269/29 "2020-07-14T17:36:16Z")

</div>

Oops! I forgot to include the `vfovToHfov` function. Updated the above post.

---

<div class="post-metadata">

**Author:** ![AndyMGar](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/andymgar/32/34306_2.png) [@AndyMGar](https://discourse.threejs.org/u/AndyMGar)\
**Post date:** [April 30, 2023, 5:52pm UTC](https://discourse.threejs.org/t/functions-to-calculate-the-visible-width-height-at-a-given-z-depth-from-a-perspective-camera/269/30 "2023-04-30T17:52:22Z")

</div>

This all looks good mathematically but the aspects are reversed I think. This works for me:

```javascript
   if (objAspect < cameraAspect) {
      // we are height constrained
      distance = _distanceToFitObjectInView(objHeight, cameraVFov)
   } else {
      // we are width constrained
      distance = _distanceToFitObjectInView(objWidth, cameraHFov)
   }

```

---

<div class="post-metadata">

**Author:** ![trusktr](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/trusktr/32/13726_2.png) [@trusktr](https://discourse.threejs.org/u/trusktr)\
**Post date:** [May 29, 2023, 11:47pm UTC](https://discourse.threejs.org/t/functions-to-calculate-the-visible-width-height-at-a-given-z-depth-from-a-perspective-camera/269/31 "2023-05-29T23:47:27Z")

</div>

It depends on what behavior you want. If you want the `cover` equivalent of [CSS `object-fit`](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit), then your conditional is the one you want. If you want the `contain` behavior, then you’d want to use the conditional in my example.

An improved version of `distanceToFitObjectToView` would have an additional `fitment` parameter that accepts values of “cover” or “contain”, and the conditional would be:

```js
// ...same as before...

  if (fitment === 'contain' ? objAspect <= cameraAspect : objAspect > cameraAspect) { // THIS CHANGED
    distance = _distanceToFitObjectInView(objHeight, cameraVFov)
  } else if (objAspect <= cameraAspect) {
    distance = _distanceToFitObjectInView(objWidth, cameraHFov)
  }

// ...same as before...

```

---

<div class="post-metadata">

**Author:** ![trusktr](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/trusktr/32/13726_2.png) [@trusktr](https://discourse.threejs.org/u/trusktr)\
**Post date:** [July 14, 2023, 5:45am UTC](https://discourse.threejs.org/t/functions-to-calculate-the-visible-width-height-at-a-given-z-depth-from-a-perspective-camera/269/32 "2023-07-14T05:45:30Z")

</div>

I added an codepen example to the [above comment](https://discourse.threejs.org/t/functions-to-calculate-the-visible-width-height-at-a-given-z-depth-from-a-perspective-camera/269/28).

---

<div class="post-metadata">

**Author:** ![AndyMGar](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/andymgar/32/34306_2.png) [@AndyMGar](https://discourse.threejs.org/u/AndyMGar)\
**Post date:** [August 14, 2023, 5:56pm UTC](https://discourse.threejs.org/t/functions-to-calculate-the-visible-width-height-at-a-given-z-depth-from-a-perspective-camera/269/33 "2023-08-14T17:56:20Z")

</div>

Thanks @trusktr, I understand where you are coming from now.

Yes, it was the contain behaviour I wanted.

---

<div class="post-metadata">

**Author:** ![sedacinar](https://avatars.discourse-cdn.com/v4/letter/s/c5a1d2/32.png) [@sedacinar](https://discourse.threejs.org/u/sedacinar)\
**Post date:** [August 15, 2023, 10:21pm UTC](https://discourse.threejs.org/t/functions-to-calculate-the-visible-width-height-at-a-given-z-depth-from-a-perspective-camera/269/34 "2023-08-15T22:21:52Z")

</div>

I was a student, i wrote my graduated project about three.js. I wrote 3d website with three.js for our university website. My lecturer was banned unity webgl. So this was very difficult for me. Now, my carrier is with webgl. I am developing still webgl games. You can see my games on [https://gameportalhub.com](https://gameportalhub.com). But i’m curious, why still you use three.js. You can also coding on unity webgl. Everything you can do with three.js, you can do with unity webgl more easily. still seeing the three.js codes made me emotional

[Previous page](https://discourse.threejs.org/t/functions-to-calculate-the-visible-width-height-at-a-given-z-depth-from-a-perspective-camera/269.md?page=1)
