diff --git a/src/components/ViewerPanel.tsx b/src/components/ViewerPanel.tsx index 0b5e48a..06981fa 100644 --- a/src/components/ViewerPanel.tsx +++ b/src/components/ViewerPanel.tsx @@ -2,6 +2,8 @@ import { CSSProperties, useContext, useEffect, useRef, useState } from 'react'; import { ModelContext } from './contexts'; +import { on } from 'events'; +import { Toast } from 'primereact/toast'; declare global { namespace JSX { @@ -11,6 +13,13 @@ declare global { } } +const PREDEFINED_ORBITS: [string, number, number][] = [ + ["Front", 0, Math.PI / 2], + ["Right", Math.PI / 2, Math.PI / 2], + ["Top", 0, 0], + ["Bottom", -Math.PI, Math.PI], +]; + export default function ViewerPanel({className, style}: {className?: string, style?: CSSProperties}) { const model = useContext(ModelContext); if (!model) throw new Error('No model'); @@ -18,6 +27,7 @@ export default function ViewerPanel({className, style}: {className?: string, sty const state = model.state; const modelViewerRef = useRef(); const axesViewerRef = useRef(); + const toastRef = useRef(null); for (const ref of [modelViewerRef, axesViewerRef]) { const otherRef = ref === modelViewerRef ? axesViewerRef : modelViewerRef; @@ -38,6 +48,25 @@ export default function ViewerPanel({className, style}: {className?: string, sty return () => element.removeEventListener('camera-change', handleCameraChange); }, [ref.current, otherRef.current]); } + + useEffect(() => { + function onClick(e: MouseEvent) { + if (e.target === axesViewerRef.current) { + // Cycle through orbits + const orbit = axesViewerRef.current.getCameraOrbit(); + const eps = 0.01; + const currentIndex = PREDEFINED_ORBITS.findIndex(([_, theta, phi]) => Math.abs(orbit.theta - theta) < eps && Math.abs(orbit.phi - phi) < eps); + const newIndex = currentIndex < 0 ? 0 : (currentIndex + 1) % PREDEFINED_ORBITS.length; + const [name, theta, phi] = PREDEFINED_ORBITS[newIndex]; + orbit.theta = theta; + orbit.phi = phi; + const newOrbit = modelViewerRef.current.cameraOrbit = axesViewerRef.current.cameraOrbit = orbit.toString(); + toastRef.current?.show({severity: 'info', detail: `${name} view`, life: 1000,}); + } + } + window.addEventListener('click', onClick); + return () => window.removeEventListener('click', onClick); + }); return (
+