Pantalla completa
This commit is contained in:
@@ -4,7 +4,7 @@ import type { OrbitControls as OrbitControlsImpl } from 'three-stdlib';
|
||||
import { Canvas } from "@react-three/fiber";
|
||||
import { useGLTF, useAnimations, Environment, Loader, OrbitControls, Html } from "@react-three/drei";
|
||||
import { Suspense, useEffect, useRef, useState } from "react";
|
||||
import { RotateCw, Play, Pause, Film, ListTree } from "lucide-react";
|
||||
import { RotateCw, Play, Pause, Film, ListTree, Shrink, Expand } from "lucide-react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Popover,
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
|
||||
import { ScrollArea } from "@/components/ui/scroll-area";
|
||||
|
||||
|
||||
// Model component
|
||||
function Model({ url, position, rotation, scale, onAnimationsLoaded, onNodesLoaded }: {
|
||||
url: string;
|
||||
@@ -56,7 +57,7 @@ function Model({ url, position, rotation, scale, onAnimationsLoaded, onNodesLoad
|
||||
);
|
||||
}
|
||||
// Preload the model
|
||||
useGLTF.preload("/3d/motor_de_combustion/scene.gltf");
|
||||
// useGLTF.preload("/3d/motor_de_combustion/scene.gltf");
|
||||
|
||||
const InitialParams = {
|
||||
position: [0, -2, 0] as [number, number, number],
|
||||
@@ -67,12 +68,14 @@ const InitialParams = {
|
||||
// Main 3D Viewer
|
||||
export default function Previewer({ modelUrl }: { modelUrl: string }) {
|
||||
const controlsRef = useRef<OrbitControlsImpl>(null);
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const [animations, setAnimations] = useState<string[]>([]);
|
||||
const [actions, setActions] = useState<Record<string, any>>({});
|
||||
const [currentAnimation, setCurrentAnimation] = useState<string | null>(null);
|
||||
|
||||
const [nodes, setNodes] = useState<string[]>([]);
|
||||
const [nodePositions, setNodePositions] = useState<Record<string, [number, number, number]>>({});
|
||||
const [isFullscreen, setIsFullscreen] = useState(false);
|
||||
|
||||
|
||||
const resetView = () => {
|
||||
@@ -96,8 +99,26 @@ export default function Previewer({ modelUrl }: { modelUrl: string }) {
|
||||
}
|
||||
};
|
||||
|
||||
// Handle Fullscreen Mode
|
||||
const toggleFullscreen = () => {
|
||||
if (!document.fullscreenElement) {
|
||||
containerRef.current?.requestFullscreen().then(() => {
|
||||
setIsFullscreen(true);
|
||||
}).catch(err => {
|
||||
console.error("Error entering fullscreen:", err);
|
||||
});
|
||||
} else {
|
||||
document.exitFullscreen().then(() => {
|
||||
setIsFullscreen(false);
|
||||
}).catch(err => {
|
||||
console.error("Error exiting fullscreen:", err);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<div className="relative w-full grow bg-white/10 shadow-xl shadow-gray-300/25 rounded-lg p-6 backdrop-blur-lg h-100">
|
||||
<div ref={containerRef} className="relative w-full grow bg-white/10 shadow-xl shadow-gray-300/25 rounded-lg p-6 backdrop-blur-lg h-100">
|
||||
<div className="z-10 absolute top-4 w-100 flex wrap gap-5">
|
||||
<Popover>
|
||||
<PopoverTrigger className="flex items-center gap-2 bg-gradient-to-r from-blue-600 to-blue-800 text-white px-4 py-2 rounded-lg shadow-lg transition-all duration-300 hover:from-blue-500 hover:to-blue-700">
|
||||
@@ -105,7 +126,7 @@ export default function Previewer({ modelUrl }: { modelUrl: string }) {
|
||||
<span>Animaciones</span>
|
||||
</PopoverTrigger>
|
||||
|
||||
<PopoverContent className="p-4 bg-blue-900 text-white w-64 my-5 mx-15">
|
||||
<PopoverContent className="p-4 bg-blue-900 text-white w-64">
|
||||
<ScrollArea className="max-h-60">
|
||||
<div className="flex flex-col gap-2">
|
||||
{animations.length > 0 ? (
|
||||
@@ -138,7 +159,7 @@ export default function Previewer({ modelUrl }: { modelUrl: string }) {
|
||||
<ListTree />
|
||||
Partes del modelo
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="p-4 bg-blue-50 text-white w-64 my-5 mx-15">
|
||||
<PopoverContent className="p-4 bg-blue-50 text-white w-64">
|
||||
<ScrollArea className="max-h-60">
|
||||
<div className="flex flex-col gap-2">
|
||||
{nodes.length > 0 ? (
|
||||
@@ -155,17 +176,23 @@ export default function Previewer({ modelUrl }: { modelUrl: string }) {
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
</div>
|
||||
{/* Reset Camera Button */}
|
||||
<div className="absolute bottom-4 right-4 z-10">
|
||||
<div className="absolute bottom-4 right-4 z-10 flex gap-4">
|
||||
<Button
|
||||
className="bg-gradient-to-r from-red-600 to-red-800 w-40 text-white px-5 py-3 rounded-lg shadow-lg transition-all duration-300 hover:from-red-500 hover:to-red-700 active:scale-95 flex items-center gap-2 justify-center"
|
||||
onClick={resetView}
|
||||
>
|
||||
<RotateCw className="w-5 h-5" />
|
||||
Reset Camera
|
||||
Centrar cámara
|
||||
</Button>
|
||||
|
||||
{/* Botón de pantalla completa */}
|
||||
<Button
|
||||
className="bg-gradient-to-r from-gray-700 to-gray-900 w-40 text-white px-5 py-3 rounded-lg shadow-lg transition-all duration-300 hover:from-gray-600 hover:to-gray-800 active:scale-95 flex items-center gap-2 justify-center"
|
||||
onClick={toggleFullscreen} >
|
||||
{isFullscreen ? <Shrink className="w-5 h-5" /> : <Expand className="w-5 h-5" />}
|
||||
{isFullscreen ? "Salir" : "Pantalla Completa"}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="w-full h-full">
|
||||
<Suspense fallback={<Loader />}>
|
||||
<Canvas camera={{ position: [0, 0, 12], fov: 20 }}>
|
||||
|
||||
Reference in New Issue
Block a user