Skip to content

Instantly share code, notes, and snippets.

@supahfunk
Last active August 1, 2023 13:16
Show Gist options
  • Save supahfunk/163b19b2d1481bb7a5ee15ea17765072 to your computer and use it in GitHub Desktop.
Save supahfunk/163b19b2d1481bb7a5ee15ea17765072 to your computer and use it in GitHub Desktop.
Converting Three.js viewport dimensions into pixel or screen percentage units
import { useEffect } from 'react'
import { useThree } from '@react-three/fiber'
import { MathUtils } from 'three'
const isPercentage = (num) => typeof num === 'string' && num.includes('%')
const calculatePosition = (side, value, size, viewport, length) => {
const { mapLinear } = MathUtils
const inverse = side === 'right' || side === 'top' ? -1 : 1
return mapLinear(parseInt(value, 10), 0, isPercentage(value) ? 100 : size, -viewport * 0.5 * inverse, viewport * 0.5 * inverse) + length * 0.5 * inverse
}
const usePixel = (ref, { left, top, bottom, right }) => {
const { viewport, size } = useThree()
useEffect(() => {
if (!ref.current) return
const { width, height } = ref.current.geometry.parameters
let x, y
if (left) x = calculatePosition('left', left, size.width, viewport.width, width)
if (right) x = calculatePosition('right', right, size.width, viewport.width, width)
if (top) y = calculatePosition('top', top, size.height, viewport.height, height)
if (bottom) y = calculatePosition('bottom', bottom, size.height, viewport.height, height)
ref.current.position.x = x
ref.current.position.y = y
})
return null
}
export default usePixel
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment