diff --git a/src/components/ComplexButtomPanel.tsx b/src/components/ButtomPanelCompass.tsx similarity index 88% rename from src/components/ComplexButtomPanel.tsx rename to src/components/ButtomPanelCompass.tsx index 435eea1..765bef9 100644 --- a/src/components/ComplexButtomPanel.tsx +++ b/src/components/ButtomPanelCompass.tsx @@ -1,12 +1,12 @@ import useModal from "../store/useModal"; -import useSequence from "../store/useSequence"; +import useCompass from "../store/useCompass"; import Button from "./Button"; import DisclaimerIcon from "./icons/DisclaimerIcon"; import DisclaimerModal from "./modals/DisclaimerModal"; -const ComplexButtomPanel = () => { +const ButtomPanelCompass = () => { const { setModal } = useModal(); - const { currentCompassRotate } = useSequence(); + const { currentCompassRotate } = useCompass(); const handleOnDisclaimerClick = () => { setModal(); @@ -40,4 +40,4 @@ const ComplexButtomPanel = () => { ); }; -export default ComplexButtomPanel; +export default ButtomPanelCompass; diff --git a/src/components/complexPage/SequenceSlider.tsx b/src/components/complexPage/SequenceSlider.tsx index 9123d46..9ccc323 100644 --- a/src/components/complexPage/SequenceSlider.tsx +++ b/src/components/complexPage/SequenceSlider.tsx @@ -8,13 +8,11 @@ import { useNavigate } from "react-router-dom"; import Button from "../Button"; import LeftArrowSliderIcon from "../icons/LeftArrowSliderIcon"; import RightArrowSliderIcon from "../icons/RightArrowSliderIcon"; -import useSequence from "../../store/useSequence"; +import useCompass from "../../store/useCompass"; import SequenceHighlighting from "./SequenceHighlighting"; const arrayLength = 360; const keyframes: number[] = [51, 178, 249, 339]; -// const keyframes: number[] = [0, 60, 120, 180, 240, 300]; -// const keyframes: number[] = [50, 177, 248, 338]; interface SequenceSliderProps { path: string; @@ -28,16 +26,11 @@ function SequenceSlider({ path }: SequenceSliderProps) { const [isAnimate, setIsAnimate] = useState(false); const [loadedImages, setLoadedImages] = useState(0); const [keyframeIndex, setKeyframeIndex] = useState(3); - const { setCurrentCompassRotate, currentCompassRotate } = useSequence(); + const { setCurrentCompassRotate, currentCompassRotate } = useCompass(); const [width, setWidth] = useState(); const [top, setTop] = useState(); const navigate = useNavigate(); - useEffect(() => { - console.log("selectedImageRightIndex", selectedImageRightIndex); - console.log("isAnimate", isAnimate); - }, [selectedImageRightIndex]); - useEffect(() => { setCurrentCompassRotate(keyframes[3]); }, []); diff --git a/src/components/icons/ChevronDownIcon.tsx b/src/components/icons/ChevronDownIcon.tsx index 9474f59..670e128 100644 --- a/src/components/icons/ChevronDownIcon.tsx +++ b/src/components/icons/ChevronDownIcon.tsx @@ -1,6 +1,11 @@ -const ChevronDownIcon = () => { +interface ChevronDownIconProps { + className?: string; +} + +const ChevronDownIcon = ({ className }: ChevronDownIconProps) => { return ( { + const materialRef = useRef(null); + const texture = useTexture(selectedSphere.sphereImage); + + useEffect(() => { + const opacity = Number(selectedSphere.id === sphere.id); + gsap.to(materialRef.current, { opacity, duration: 1 }); + }, [selectedSphere, sphere]); + + return ( + + + + ); +}; + +export default SphereTour; diff --git a/src/components/virtualTour/VirtualTourWrapper.tsx b/src/components/virtualTour/VirtualTourWrapper.tsx index 98b5f00..2265f33 100644 --- a/src/components/virtualTour/VirtualTourWrapper.tsx +++ b/src/components/virtualTour/VirtualTourWrapper.tsx @@ -1,39 +1,58 @@ -import { BackSide, MeshBasicMaterial } from "three"; -import { OrbitControls, Html, Sphere, useTexture } from "@react-three/drei"; -import { Suspense, useRef } from "react"; +import { OrbitControls, Html, useTexture } from "@react-three/drei"; +import { Suspense, useEffect, useRef, useState } from "react"; import { OrbitControls as OrbitControlsImpl } from "three-stdlib"; import { useParams } from "react-router-dom"; +import useCompass from "../../store/useCompass"; +import SphereTour from "./SphereTour"; +import { spheres } from "../../consts/spheres"; +import useSphere from "../../store/useSphere"; const VirtualTourWrapper = () => { const orbitRef = useRef(null); - const materialRef = useRef(null); - const texture = useTexture( - "/images/virtual-tour/studio1/Studio1_w-12_13_sp-01.webp" - ); + + const { setCurrentCompassRotate, currentCompassRotate } = useCompass(); const { id } = useParams(); + const [startRotatingPos, setStartRotatingPos] = useState(0); + const { selectedSphere, setSelectedSphere } = useSphere(); + // const [selectedSphere, setSelectedSphere] = useState( + // spheres[1] + // ); + useEffect(() => { + setSelectedSphere(spheres[0]); + }, []); + + const handleOnRotating = () => { + const radian = orbitRef.current?.getAzimuthalAngle(); + if (radian) { + const currentCompasDegrees = (radian * 180) / Math.PI + 180; + const compassOffsetDegres = startRotatingPos - currentCompasDegrees; + setCurrentCompassRotate(currentCompassRotate + compassOffsetDegres); + } + }; return ( - Loading ...}> - - +
Loading
+ + } + > + {spheres.map((sphere) => ( + - + ))} console.log("e", orbitRef.current?.getAzimuthalAngle())} + // onStart={(e) => console.log("e", e)} + // onChange={(e) => console.log("e", e?.target)} + onChange={handleOnRotating} target={[-14.16, 0, 24.11]} /> diff --git a/src/consts/spheres.ts b/src/consts/spheres.ts new file mode 100644 index 0000000..9ee68ed --- /dev/null +++ b/src/consts/spheres.ts @@ -0,0 +1,41 @@ +import { IAppartmentSphere } from "../types/apartmentSphere"; + +const spheres: IAppartmentSphere[] = [ + { + id: "1", + sphereImage: "/images/virtual-tour/studio1/Studio1_w-12_13_sp-01.webp", + roomType: "room 1", + }, + { + id: "2", + sphereImage: "/images/virtual-tour/studio1/Studio1_w-12_13_sp-02.webp", + roomType: "room 2", + }, + { + id: "3", + sphereImage: "/images/virtual-tour/studio1/Studio1_w-12_13_sp-03.webp", + roomType: "room 3", + }, + { + id: "4", + sphereImage: "/images/virtual-tour/studio1/Studio1_w-12_13_sp-04.webp", + roomType: "room 4", + }, + { + id: "5", + sphereImage: "/images/virtual-tour/studio1/Studio1_w-12_13_sp-05.webp", + roomType: "room 5", + }, + { + id: "6", + sphereImage: "/images/virtual-tour/studio1/Studio1_w-12_13_sp-06.webp", + roomType: "room 6", + }, + { + id: "7", + sphereImage: "/images/virtual-tour/studio1/Studio1_w-12_13_sp-07.webp", + roomType: "room 7", + }, +]; + +export { spheres }; diff --git a/src/pages/Complex.tsx b/src/pages/Complex.tsx index e31fbec..debb275 100644 --- a/src/pages/Complex.tsx +++ b/src/pages/Complex.tsx @@ -1,4 +1,4 @@ -import ComplexButtomPanel from "../components/ComplexButtomPanel"; +import ButtomPanelCompass from "../components/ButtomPanelCompass"; import ComplexTopPanel from "../components/complexPage/ComplexTopPanel"; import SequenceSlider from "../components/complexPage/SequenceSlider"; @@ -7,7 +7,7 @@ const Complex = () => {
- +
); }; diff --git a/src/pages/ComplexWing.tsx b/src/pages/ComplexWing.tsx index 80f57dc..3a07cff 100644 --- a/src/pages/ComplexWing.tsx +++ b/src/pages/ComplexWing.tsx @@ -1,5 +1,5 @@ import ComplexTopPanel from "../components/complexPage/ComplexTopPanel"; -import ComplexButtomPanel from "../components/ComplexButtomPanel"; +import ButtomPanelCompass from "../components/ButtomPanelCompass"; import SequenceWing from "../components/complexWingPage/SequenceWing"; const ComplexWing = () => { @@ -7,7 +7,7 @@ const ComplexWing = () => {
- +
); }; diff --git a/src/pages/VirtualTour.tsx b/src/pages/VirtualTour.tsx index 30a91fc..54519db 100644 --- a/src/pages/VirtualTour.tsx +++ b/src/pages/VirtualTour.tsx @@ -1,14 +1,32 @@ +import { useState } from "react"; import { Canvas } from "@react-three/fiber"; -import ButtomPanel from "../components/ButtomPanel"; import VirtualTourWrapper from "../components/virtualTour/VirtualTourWrapper"; +import Button from "../components/Button"; +import HeartIcon from "../components/icons/Heart"; +import ChevronDownIcon from "../components/icons/ChevronDownIcon"; +import ButtomPanelCompass from "../components/ButtomPanelCompass"; +import BookingIcon from "../components/icons/BookingIcon"; +import { spheres } from "../consts/spheres"; +import { IAppartmentSphere } from "../types/apartmentSphere"; +import useSphere from "../store/useSphere"; const VirtualTour = () => { + const [isActive, setIsActive] = useState(false); + const { setSelectedSphere } = useSphere(); + + const handleOnShowClick = () => { + setIsActive((prev) => !prev); + }; + + const handleOnLabelClick = (sphere: IAppartmentSphere) => { + setSelectedSphere(sphere); + }; + return (
- {/* */}
-
+

Rove Home Marasi Drive{" "} @@ -25,13 +43,94 @@ const VirtualTour = () => {

№ 213

+
+
+
+ 234 +
+

+ 1 bedroom appartment +

+
+
+
+
+
+
+

Size

+

609 Sqft

+
+
+

Status

+

Available

+
+
+
+
+
+
+
+
+
+ {spheres.map((sphere) => { + return ( +
handleOnLabelClick(sphere)} + className="bg-[#F3F3F2] font-semibold text-[#0D1922] text-caption-s py-0.5 px-2 w-fit rounded-full cursor-pointer pointer-events-auto select-none" + key={sphere.id} + > + {sphere.roomType} +
+ ); + })} +
+
+
+
+
+ Show +
+
+ Hide +
+
+ +
+
+
- +
); }; diff --git a/src/store/useSequence.tsx b/src/store/useCompass.tsx similarity index 77% rename from src/store/useSequence.tsx rename to src/store/useCompass.tsx index cbbec41..835b017 100644 --- a/src/store/useSequence.tsx +++ b/src/store/useCompass.tsx @@ -5,10 +5,10 @@ interface SequenceStore { setCurrentCompassRotate: (keyframe: number) => void; } -const useSequence = create((set) => ({ +const useCompass = create((set) => ({ currentCompassRotate: 0, setCurrentCompassRotate: (keyframe) => set(() => ({ currentCompassRotate: keyframe })), })); -export default useSequence; +export default useCompass; diff --git a/src/store/useSphere.tsx b/src/store/useSphere.tsx new file mode 100644 index 0000000..65df788 --- /dev/null +++ b/src/store/useSphere.tsx @@ -0,0 +1,13 @@ +import { create } from "zustand"; +import { IAppartmentSphere } from "../types/apartmentSphere"; + +interface SequenceStore { + selectedSphere: null | IAppartmentSphere; + setSelectedSphere: (sphere: null | IAppartmentSphere) => void; +} + +const useSphere = create((set) => ({ + selectedSphere: null, + setSelectedSphere: (sphere) => set(() => ({ selectedSphere: sphere })), +})); +export default useSphere; diff --git a/src/types/apartmentSphere.ts b/src/types/apartmentSphere.ts new file mode 100644 index 0000000..6dfdeea --- /dev/null +++ b/src/types/apartmentSphere.ts @@ -0,0 +1,7 @@ +interface IAppartmentSphere { + id: string; + sphereImage: string; + roomType: string; +} + +export type { IAppartmentSphere };