Skip to main content

Helpers

Conversions between the scene and the canvas, for apps that draw their own 3D overlays.

Objects​

CameraHelper​

const CameraHelper: {
calculateNearFar: (camera, box) => {
far: number;
near: number;
};
calculateScaleFactor(point3, radiusPx, camera, size): number;
getPoint2(point3, camera, size): Vector3;
getPoint3(point2, camera, size, zValue): Vector3;
};

Conversions between the 3D scene and the pixels of the canvas, for a camera and the canvas' size.

In a react-three-fiber component, camera and size come from useThree().

Type Declaration​

NameTypeDescription
calculateNearFar()(camera, box) => { far: number; near: number; }The near and far distances that just enclose a box, for an orthographic camera looking at it.
calculateScaleFactor()( point3, radiusPx, camera, size ) => numberThe size in scene units that appears radiusPx pixels large on the canvas, at the position point3. Scale an object of unit size by it to keep it the same size on screen, whatever the zoom.
getPoint2()( point3, camera, size ) => Vector3Projects a point of the scene onto the canvas. Note that it projects point3 in place: pass a clone to keep the original.
getPoint3()( point2, camera, size, zValue? ) => Vector3Projects a point of the canvas into the scene.

Example​

A handle that keeps 8 pixels wide however far the camera zooms, and a label at a point of the model:

import { useRef } from 'react'
import * as THREE from 'three'
import { useFrame, useThree } from '@react-three/fiber'
import { CameraHelper } from '@buerli.io/react'

function Handle({ position }: { position: THREE.Vector3 }) {
const ref = useRef<THREE.Mesh>(null)
useFrame(({ camera, size }) => {
ref.current?.scale.setScalar(CameraHelper.calculateScaleFactor(position, 8, camera, size))
})
return (
<mesh ref={ref} position={position}>
<sphereGeometry args={[1]} />
</mesh>
)
}

function useScreenPosition(point: THREE.Vector3) {
const { camera, size } = useThree()
// getPoint2 projects in place: pass a copy
const { x, y } = CameraHelper.getPoint2(point.clone(), camera, size)
return { left: x, top: y }
}