Skip to content

Commit

Permalink
Layout fixes; dynamic FOV based on window size
Browse files Browse the repository at this point in the history
  • Loading branch information
zfox23 committed Sep 23, 2024
1 parent 1f9c85f commit f3525b1
Showing 1 changed file with 43 additions and 10 deletions.
53 changes: 43 additions & 10 deletions src/components/Viewer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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;

Expand All @@ -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);
Expand Down Expand Up @@ -73,6 +97,13 @@ export default function Viewer() {
setIsDraggingOver(false);
};

useEffect(() => {
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
};
}, []);

return (
<div className='w-full h-full min-h-screen bg-black absolute flex items-center' onDragOver={handleDragOver} onDrop={handleDrop} onDragLeave={handleDragLeave}>
<Canvas
Expand All @@ -90,14 +121,16 @@ export default function Viewer() {
</XR>
</Canvas>

<div className='fixed left-1/2 -translate-x-1/2 bottom-0 bg-white/80 flex justify-center gap-4 md:gap-12 p-4 rounded-t-md'>
<div className='flex flex-col gap-1'>
<p className='font-semibold'>Drop or select an Apple Spatial Photo <span className='font-mono'>(.heic)</span></p>
<input className='cursor-pointer' type="file" accept=".heic" onChange={processBrowsedFile} />
<p className='text-xs italic'>Your photo is processed on your device.</p>
</div>
<div className='fixed w-full flex justify-center bottom-0'>
<div className='absolute mx-4 bottom-4 bg-white/80 flex justify-center items-stretch flex-wrap gap-y-4 gap-x-8 p-2 md:p-4 rounded-md'>
<div className='flex flex-col gap-1'>
<p className='font-semibold'>Drop or select an Apple Spatial Photo <span className='font-mono'>(.heic)</span></p>
<input className='cursor-pointer' type="file" accept=".heic" onChange={processBrowsedFile} />
<p className='text-xs italic'>Your photo is processed on your device.</p>
</div>

<button className='bg-amber-600 outline-double outline-0 hover:outline-2 active:outline-4 focus:outline-2 outline-white text-white px-8 py-2 font-semibold text-xl rounded-md transition-all duration-[25ms]' onClick={onXRButtonClicked}>{isInXR ? 'Exit' : 'Enter'} VR</button>
<button className='bg-amber-600 outline-double outline-0 hover:outline-2 active:outline-4 focus:outline-2 outline-white text-white px-8 py-2 font-semibold text-xl rounded-md transition-all duration-[25ms]' onClick={onXRButtonClicked}>{isInXR ? 'Exit' : 'Enter'} VR</button>
</div>
</div>

<div className={`absolute inset-0 rounded-md border-dashed border-2 border-white bg-neutral-800/90 text-amber-500 font-semibold text-xl md:text-2xl flex-col gap-2 justify-center items-center ${isDraggingOver ? "flex" : "hidden"} pointer-events-none`}>
Expand Down

0 comments on commit f3525b1

Please sign in to comment.