Cycle through predefined orbits when tapping axes
This commit is contained in:
parent
909e4a8231
commit
062c89a45b
1 changed files with 31 additions and 0 deletions
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
import { CSSProperties, useContext, useEffect, useRef, useState } from 'react';
|
import { CSSProperties, useContext, useEffect, useRef, useState } from 'react';
|
||||||
import { ModelContext } from './contexts';
|
import { ModelContext } from './contexts';
|
||||||
|
import { on } from 'events';
|
||||||
|
import { Toast } from 'primereact/toast';
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
namespace JSX {
|
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}) {
|
export default function ViewerPanel({className, style}: {className?: string, style?: CSSProperties}) {
|
||||||
const model = useContext(ModelContext);
|
const model = useContext(ModelContext);
|
||||||
if (!model) throw new Error('No model');
|
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 state = model.state;
|
||||||
const modelViewerRef = useRef<any>();
|
const modelViewerRef = useRef<any>();
|
||||||
const axesViewerRef = useRef<any>();
|
const axesViewerRef = useRef<any>();
|
||||||
|
const toastRef = useRef<Toast>(null);
|
||||||
|
|
||||||
for (const ref of [modelViewerRef, axesViewerRef]) {
|
for (const ref of [modelViewerRef, axesViewerRef]) {
|
||||||
const otherRef = ref === modelViewerRef ? axesViewerRef : modelViewerRef;
|
const otherRef = ref === modelViewerRef ? axesViewerRef : modelViewerRef;
|
||||||
|
|
@ -28,6 +38,7 @@ export default function ViewerPanel({className, style}: {className?: string, sty
|
||||||
if (!otherRef.current) return;
|
if (!otherRef.current) return;
|
||||||
if (e.detail.source === 'user-interaction') {
|
if (e.detail.source === 'user-interaction') {
|
||||||
const cameraOrbit = ref.current.getCameraOrbit();
|
const cameraOrbit = ref.current.getCameraOrbit();
|
||||||
|
console.log(cameraOrbit.toString());
|
||||||
cameraOrbit.radius = otherRef.current.getCameraOrbit().radius;
|
cameraOrbit.radius = otherRef.current.getCameraOrbit().radius;
|
||||||
|
|
||||||
otherRef.current.cameraOrbit = cameraOrbit.toString();
|
otherRef.current.cameraOrbit = cameraOrbit.toString();
|
||||||
|
|
@ -38,6 +49,25 @@ export default function ViewerPanel({className, style}: {className?: string, sty
|
||||||
return () => element.removeEventListener('camera-change', handleCameraChange);
|
return () => element.removeEventListener('camera-change', handleCameraChange);
|
||||||
}, [ref.current, otherRef.current]);
|
}, [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 (
|
return (
|
||||||
<div className={className}
|
<div className={className}
|
||||||
|
|
@ -49,6 +79,7 @@ export default function ViewerPanel({className, style}: {className?: string, sty
|
||||||
width: '100%',
|
width: '100%',
|
||||||
...(style ?? {})
|
...(style ?? {})
|
||||||
}}>
|
}}>
|
||||||
|
<Toast ref={toastRef} position='bottom-right' />
|
||||||
<model-viewer
|
<model-viewer
|
||||||
orientation="0deg -90deg 0deg"
|
orientation="0deg -90deg 0deg"
|
||||||
class="main-viewer"
|
class="main-viewer"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue