From 49da64140c05055eff7319d7263acfe7189ced1f Mon Sep 17 00:00:00 2001 From: Vishnu <vishnu@hexrfactory.com> Date: Fri, 9 May 2025 10:18:13 +0530 Subject: [PATCH] Enhance sidebar animations: improve open/close transitions and add reveal effects for sidebar elements. --- app/src/components/ui/list/DropDownList.tsx | 1 + .../collaboration/camera/collabCams.tsx | 9 +- .../instances/animator/vehicleAnimator.tsx | 3 +- .../visualization/zone/zoneCameraTarget.tsx | 172 +++++++++--------- app/src/styles/layout/sidebar.scss | 66 ++++--- 5 files changed, 146 insertions(+), 105 deletions(-) diff --git a/app/src/components/ui/list/DropDownList.tsx b/app/src/components/ui/list/DropDownList.tsx index 2a77303..89971a2 100644 --- a/app/src/components/ui/list/DropDownList.tsx +++ b/app/src/components/ui/list/DropDownList.tsx @@ -123,6 +123,7 @@ const DropDownList: React.FC<DropDownListProps> = ({ </div> )} <button + title="collapse-btn" className="collapse-icon option" style={{ transform: isOpen ? "rotate(0deg)" : "rotate(-90deg)" }} onClick={handleToggle} diff --git a/app/src/modules/collaboration/camera/collabCams.tsx b/app/src/modules/collaboration/camera/collabCams.tsx index 6ce26b0..fab6efe 100644 --- a/app/src/modules/collaboration/camera/collabCams.tsx +++ b/app/src/modules/collaboration/camera/collabCams.tsx @@ -12,6 +12,7 @@ import CollabUserIcon from "./collabUserIcon"; import useModuleStore from "../../../store/useModuleStore"; import { getAvatarColor } from "../functions/getAvatarColor"; import { useSelectedUserStore } from "../../../store/useCollabStore"; +import { usePlayButtonStore } from "../../../store/usePlayButtonStore"; const CamModelsGroup = () => { const navigate = useNavigate(); @@ -21,6 +22,7 @@ const CamModelsGroup = () => { const { socket } = useSocketStore(); const { activeModule } = useModuleStore(); const { selectedUser, setSelectedUser } = useSelectedUserStore(); + const { isPlaying } = usePlayButtonStore(); // eslint-disable-next-line react-hooks/exhaustive-deps const loader = new GLTFLoader(); @@ -244,7 +246,8 @@ const CamModelsGroup = () => { object={cam} visible={ selectedUser?.name !== cam.userData.userName && - activeModule !== "visualization" + activeModule !== "visualization" && + !isPlaying } > <Html @@ -258,7 +261,9 @@ const CamModelsGroup = () => { fontFamily: "Arial, sans-serif", display: `${activeModule !== "visualization" ? "" : "none"}`, opacity: `${ - selectedUser?.name !== cam.userData.userName ? 1 : 0 + selectedUser?.name !== cam.userData.userName && !isPlaying + ? 1 + : 0 }`, transition: "opacity .2s ease", }} diff --git a/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx b/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx index ba16302..d2ecfc3 100644 --- a/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx +++ b/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx @@ -146,7 +146,8 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai return ( <> {currentPath.length > 0 && ( - <group > + // helper + <group visible={false}> <Line points={currentPath} color="blue" lineWidth={3} /> {currentPath.map((point, index) => ( <mesh key={index} position={point}> diff --git a/app/src/modules/visualization/zone/zoneCameraTarget.tsx b/app/src/modules/visualization/zone/zoneCameraTarget.tsx index c3116ef..1417e58 100644 --- a/app/src/modules/visualization/zone/zoneCameraTarget.tsx +++ b/app/src/modules/visualization/zone/zoneCameraTarget.tsx @@ -2,90 +2,100 @@ import { useEffect, useMemo, useRef, useState } from "react"; import { useFrame, useThree } from "@react-three/fiber"; import * as THREE from "three"; import { useSelectedZoneStore } from "../../../store/visualization/useZoneStore"; -import { useEditPosition, usezonePosition, usezoneTarget } from "../../../store/store"; +import { + useEditPosition, + usezonePosition, + usezoneTarget, +} from "../../../store/store"; export default function ZoneCentreTarget() { - const { selectedZone, setSelectedZone } = useSelectedZoneStore(); - const [previousZoneCentre, setPreviousZoneCentre] = useState<number[] | null>(null); - const sphereRef = useRef<THREE.Mesh>(null); - const { camera, controls }: any = useThree(); - const { zonePosition, setZonePosition } = usezonePosition(); - const { zoneTarget, setZoneTarget } = usezoneTarget(); - const { Edit, setEdit } = useEditPosition(); + const { selectedZone } = useSelectedZoneStore(); + const [previousZoneCentre, setPreviousZoneCentre] = useState<number[] | null>( + null + ); + const sphereRef = useRef<THREE.Mesh>(null); + const { controls }: any = useThree(); + const { setZonePosition } = usezonePosition(); + const { setZoneTarget } = usezoneTarget(); + const { Edit } = useEditPosition(); - useEffect(() => { - if ( - selectedZone.zoneViewPortTarget && - JSON.stringify(previousZoneCentre) !== JSON.stringify(selectedZone.zoneViewPortTarget) - ) { - setPreviousZoneCentre(selectedZone.zoneViewPortTarget); - } - }, [selectedZone.zoneViewPortTarget, previousZoneCentre]); + useEffect(() => { + if ( + selectedZone.zoneViewPortTarget && + JSON.stringify(previousZoneCentre) !== + JSON.stringify(selectedZone.zoneViewPortTarget) + ) { + setPreviousZoneCentre(selectedZone.zoneViewPortTarget); + } + }, [selectedZone.zoneViewPortTarget, previousZoneCentre]); - const centrePoint = useMemo(() => { - if (!previousZoneCentre || !selectedZone.zoneViewPortTarget) return null; - return previousZoneCentre.map((value, index) => - (value + selectedZone.zoneViewPortTarget[index]) / 2 - ); - }, [previousZoneCentre, selectedZone.zoneViewPortTarget]); - - useEffect(() => { - if (selectedZone.zoneName !== "") { - if (sphereRef.current) { - sphereRef.current.position.set(selectedZone.zoneViewPortTarget[0], selectedZone.zoneViewPortTarget[1], selectedZone.zoneViewPortTarget[2]); - } - if (centrePoint) { - - if (centrePoint.length > 0) { - - // let camPosition = new THREE.Vector3(...selectedZone.zoneViewPortPosition); - // let CamTarget = new THREE.Vector3(...selectedZone.zoneViewPortTarget); - - // const direction = new THREE.Vector3().subVectors(CamTarget, camPosition).normalize(); - - // const worldUp = new THREE.Vector3(0, 0, 1); - // const right = new THREE.Vector3().crossVectors(worldUp, direction).normalize(); - // const up = new THREE.Vector3().crossVectors(direction, right).normalize(); - // const offsetPosition = up.clone().multiplyScalar(20); - // camPosition.add(offsetPosition); - - const setCam = async () => { - controls.setLookAt(centrePoint[0], 100, centrePoint[2], ...centrePoint, true); - setTimeout(() => { - controls?.setLookAt( - ...selectedZone.zoneViewPortPosition, - selectedZone.zoneViewPortTarget[0], - selectedZone.zoneViewPortTarget[1], - selectedZone.zoneViewPortTarget[2], - true - ); - }, 400) - }; - setCam(); - } else { - - const setCam = async () => { - controls?.setLookAt( - ...selectedZone.zoneViewPortPosition, - selectedZone.zoneViewPortTarget[0], - selectedZone.zoneViewPortTarget[1], - selectedZone.zoneViewPortTarget[2], - true - ); - }; - setCam(); - } - } - } - }, [selectedZone.zoneViewPortTarget]); - - useFrame(() => { - if (Edit) { - setZonePosition([controls.getPosition().x, controls.getPosition().y, controls.getPosition().z]) - setZoneTarget([controls.getTarget().x, controls.getTarget().y, controls.getTarget().z]) - } - }) - return ( - <> </> + const centrePoint = useMemo(() => { + if (!previousZoneCentre || !selectedZone.zoneViewPortTarget) return null; + return previousZoneCentre.map( + (value, index) => (value + selectedZone.zoneViewPortTarget[index]) / 2 ); + }, [previousZoneCentre, selectedZone.zoneViewPortTarget]); + + useEffect(() => { + if (selectedZone.zoneName !== "") { + if (sphereRef.current) { + sphereRef.current.position.set( + selectedZone.zoneViewPortTarget[0], + selectedZone.zoneViewPortTarget[1], + selectedZone.zoneViewPortTarget[2] + ); + } + if (centrePoint) { + if (centrePoint.length > 0) { + const setCam = async () => { + controls.setLookAt( + centrePoint[0], + 100, + centrePoint[2], + ...centrePoint, + true + ); + setTimeout(() => { + controls?.setLookAt( + ...selectedZone.zoneViewPortPosition, + selectedZone.zoneViewPortTarget[0], + selectedZone.zoneViewPortTarget[1], + selectedZone.zoneViewPortTarget[2], + true + ); + }, 400); + }; + setCam(); + } else { + const setCam = async () => { + controls?.setLookAt( + ...selectedZone.zoneViewPortPosition, + selectedZone.zoneViewPortTarget[0], + selectedZone.zoneViewPortTarget[1], + selectedZone.zoneViewPortTarget[2], + true + ); + }; + setCam(); + } + } + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [selectedZone.zoneViewPortTarget]); + + useFrame(() => { + if (Edit) { + setZonePosition([ + controls.getPosition().x, + controls.getPosition().y, + controls.getPosition().z, + ]); + setZoneTarget([ + controls.getTarget().x, + controls.getTarget().y, + controls.getTarget().z, + ]); + } + }); + return <></>; } diff --git a/app/src/styles/layout/sidebar.scss b/app/src/styles/layout/sidebar.scss index 6e1889e..f14d769 100644 --- a/app/src/styles/layout/sidebar.scss +++ b/app/src/styles/layout/sidebar.scss @@ -1437,9 +1437,11 @@ width: 100%; height: 100%; font-size: var(--font-size-regular); - background: linear-gradient(0deg, - rgba(37, 24, 51, 0) 0%, - rgba(52, 41, 61, 0.5) 100%); + background: linear-gradient( + 0deg, + rgba(37, 24, 51, 0) 0%, + rgba(52, 41, 61, 0.5) 100% + ); pointer-events: none; backdrop-filter: blur(8px); opacity: 0; @@ -1480,26 +1482,48 @@ .sidebar-left-wrapper, .sidebar-right-wrapper { - height: calc(54vh + 150px); transition: height 0.2s ease-in-out; - .sidebar-left-container { - height: 100%; - .sidebar-left-content-container{ - max-height: 80%; - .widget-left-sideBar{ - height: 80%; - .widget2D.widgets-wrapper{ - - min-height: 50vh; - height: 60%; - - } - } - } - } } .sidebar-left-wrapper.closed, .sidebar-right-wrapper.closed { - height: 52px; -} \ No newline at end of file + animation: closeSidebar 0.2s linear forwards; +} + +.sidebar-left-wrapper.open, +.sidebar-right-wrapper.open { + height: fit-content; + animation: openSidebar 0.2s linear; + .sidebar-right-container, + .sidebar-left-container { + opacity: 0; + animation: revealSmooth 0.3s 0.1s linear forwards; + } +} + +@keyframes revealSmooth { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +@keyframes closeSidebar{ + from{ + height: 60%; + } + to{ + height: 52px; + } +} + +@keyframes openSidebar{ + from{ + height: 52px; + } + to{ + height: 60%; + } +}