diff --git a/src/components/Viewer.jsx b/src/components/Viewer.jsx index 84a3e68..b3d4c17 100644 --- a/src/components/Viewer.jsx +++ b/src/components/Viewer.jsx @@ -2,7 +2,7 @@ import { Canvas } from '@react-three/fiber'; import { XR, XROrigin, createXRStore } from '@react-three/xr'; import * as THREE from 'three'; import ImmersiveImageMesh from './ImmersiveImageMesh'; -import { useRef, useState } from 'react'; +import { useEffect, useRef, useState } from 'react'; import { PerspectiveCamera } from '@react-three/drei'; const store = createXRStore(); @@ -14,12 +14,37 @@ const cameraLayers = new THREE.Layers(); cameraLayers.enable(0); cameraLayers.enable(1); +const clamp = (val, min, max) => { + return Math.min(Math.max(val, min), max); +} + +const linearScale = (factor, minInput, maxInput, minOutput, maxOutput, shouldClamp = true) => { + if (shouldClamp) { + factor = clamp(factor, minInput, maxInput); + } + + return minOutput + (maxOutput - minOutput) * + (factor - minInput) / (maxInput - minInput); +} + export default function Viewer() { const [imageSrc, setImageSrc] = useState(""); const [isInXR, setIsInXR] = useState(false); const [isDraggingOver, setIsDraggingOver] = useState(false); const cameraRef = useRef(); + const resetFOV = () => { + // Experimentally determined values + cameraRef.current.fov = linearScale(window.innerWidth / window.innerHeight, 0.30, 2.5, 120, 70, true); + cameraRef.current.updateProjectionMatrix(); + } + + const handleResize = () => { + if (!isInXR && cameraRef.current) { + resetFOV(); + } + }; + const processBrowsedFile = (e) => { if (!(e.target.files && e.target.files.length)) return; @@ -39,8 +64,7 @@ export default function Viewer() { if (!newIsInXR && cameraRef.current) { cameraRef.current.rotation.set(...DEFAULT_CAMERA_ROTATION); cameraRef.current.position.set(...DEFAULT_CAMERA_POSITION_M); - cameraRef.current.fov = DEFAULT_FOV; - cameraRef.current.updateProjectionMatrix(); + resetFOV(); } setIsInXR(newIsInXR); @@ -73,6 +97,13 @@ export default function Viewer() { setIsDraggingOver(false); }; + useEffect(() => { + window.addEventListener('resize', handleResize); + return () => { + window.removeEventListener('resize', handleResize); + }; + }, []); + return (
-
-
-

Drop or select an Apple Spatial Photo (.heic)

- -

Your photo is processed on your device.

-
+
+
+
+

Drop or select an Apple Spatial Photo (.heic)

+ +

Your photo is processed on your device.

+
- + +