threlte logo
@threlte/extras

useViewport

The useViewport hook returns a viewport which provides information related to the screen.

<script lang="ts">
  import { Canvas } from '@threlte/core'
  import Scene from './Scene.svelte'
</script>

<div>
  <Canvas>
    <Scene />
  </Canvas>
</div>

<style>
  div {
    height: 100%;
  }
</style>
<script lang="ts">
  import type { Mesh } from 'three'
  import { T, useTask, useThrelte } from '@threlte/core'
  import { OrbitControls, useViewport, RoundedBoxGeometry } from '@threlte/extras'

  const viewport = useViewport()
  const { renderStage, scheduler } = useThrelte()

  let ref: Mesh

  const positions: [number, number, number][] = [
    [1, 0.5, 3.5],
    [-1, 0.5, -3.5],
    [-1, 0.5, 3.5],
    [1, 0.5, -3.5]
  ]

  useTask(
    () => {
      const { width, height, distance } = viewport.current
      ref.scale.set(width * 0.4, height * 0.2, distance * 0.25)
      ref.position.y = ref.scale.y / 2
    },
    {
      stage: scheduler.createStage(Symbol('viewport-stage'), { before: renderStage })
    }
  )
</script>

<T.PerspectiveCamera
  makeDefault
  position={[8, 8, 8]}
  fov={50}
>
  <OrbitControls
    minDistance={5}
    maxDistance={15}
    enableDamping
    autoRotate
  />
</T.PerspectiveCamera>

<T.DirectionalLight
  castShadow
  position={[3, 5, 3]}
  intensity={1.5}
/>

<T.AmbientLight />

<T.Mesh
  bind:ref
  castShadow
  receiveShadow
>
  <RoundedBoxGeometry radius={0.1} />
  <T.MeshStandardMaterial color="turquoise" />
</T.Mesh>

{#each positions as position}
  <T.Mesh
    castShadow
    {position}
  >
    <T.DodecahedronGeometry args={[0.5]} />
    <T.MeshToonMaterial color="#fff" />
  </T.Mesh>
{/each}

<T.Mesh
  rotation.x={-Math.PI / 2}
  scale={6}
  receiveShadow
>
  <T.CircleGeometry args={[1, 128]} />
  <T.MeshToonMaterial color="#ccc" />
</T.Mesh>

The width and height properties provide the screen size in Three.js units. For example, the following mesh would fill the entire screen:

<script>
  import { T } from '@threlte/core'
  import { useViewport } from '@threlte/extras'

  const viewport = useViewport() // currentWritable<Viewport>
</script>

<T.Mesh scale={[$viewport.width, $viewport.height, 1]}>
  <T.PlaneGeometry />
  <T.MeshStandardMaterial />
</T.Mesh>

The factor property is the canvas width divided by the viewport width.

The distance property is the camera distance from an origin point. The default origin is 0,0,0, but a custom origin can be passed into the hook.

const viewport = useViewport([1, 0, 1])