feat(web): clamp tabletop camera to the horizon
Add a maxPolarAngle prop to Scene and use it in the tabletop view so the camera can't dip below the table and peek under face-down cards.
This commit is contained in:
@@ -56,6 +56,9 @@ export default function TabletopScene({
|
|||||||
enablePan
|
enablePan
|
||||||
fullscreen
|
fullscreen
|
||||||
shadowScale={shadowScale}
|
shadowScale={shadowScale}
|
||||||
|
// Keep the camera above the table so face-down cards can't be peeked
|
||||||
|
// from below. π/2 clamps the polar angle at the horizon.
|
||||||
|
maxPolarAngle={Math.PI / 2}
|
||||||
overlay={
|
overlay={
|
||||||
<button
|
<button
|
||||||
onClick={() => setShowSurface((v) => !v)}
|
onClick={() => setShowSurface((v) => !v)}
|
||||||
|
|||||||
@@ -16,7 +16,9 @@ import { EffectComposer, Vignette } from '@react-three/postprocessing';
|
|||||||
*
|
*
|
||||||
* `autoRotate` and `enablePan` tune the orbit controls (a tabletop view, for
|
* `autoRotate` and `enablePan` tune the orbit controls (a tabletop view, for
|
||||||
* example, pans instead of rotating). `fullscreen` adds a toggle button that
|
* example, pans instead of rotating). `fullscreen` adds a toggle button that
|
||||||
* expands the scene to the full screen.
|
* expands the scene to the full screen. `maxPolarAngle` (radians) clamps how
|
||||||
|
* far the camera can tilt below the horizon, e.g. to stop a tabletop view from
|
||||||
|
* peeking under face-down cards.
|
||||||
*/
|
*/
|
||||||
export default function Scene({
|
export default function Scene({
|
||||||
children,
|
children,
|
||||||
@@ -25,6 +27,7 @@ export default function Scene({
|
|||||||
fullscreen = false,
|
fullscreen = false,
|
||||||
overlay,
|
overlay,
|
||||||
shadowScale = 22,
|
shadowScale = 22,
|
||||||
|
maxPolarAngle = Math.PI,
|
||||||
}: {
|
}: {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
autoRotate?: boolean;
|
autoRotate?: boolean;
|
||||||
@@ -34,6 +37,8 @@ export default function Scene({
|
|||||||
overlay?: ReactNode;
|
overlay?: ReactNode;
|
||||||
/** Contact shadow plane size in world units; defaults to a generous 22. */
|
/** Contact shadow plane size in world units; defaults to a generous 22. */
|
||||||
shadowScale?: number;
|
shadowScale?: number;
|
||||||
|
/** Max camera polar angle in radians; defaults to unrestricted (π). */
|
||||||
|
maxPolarAngle?: number;
|
||||||
}) {
|
}) {
|
||||||
const containerRef = useRef<HTMLDivElement>(null);
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
const [isFullscreen, setIsFullscreen] = useState(false);
|
const [isFullscreen, setIsFullscreen] = useState(false);
|
||||||
@@ -93,6 +98,7 @@ export default function Scene({
|
|||||||
enablePan={enablePan}
|
enablePan={enablePan}
|
||||||
minDistance={0.01}
|
minDistance={0.01}
|
||||||
maxDistance={8}
|
maxDistance={8}
|
||||||
|
maxPolarAngle={maxPolarAngle}
|
||||||
autoRotate={autoRotate}
|
autoRotate={autoRotate}
|
||||||
makeDefault
|
makeDefault
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user