diff --git a/src/app/(main)/layout.tsx b/src/app/(main)/layout.tsx index 79bf3c1..c91b392 100644 --- a/src/app/(main)/layout.tsx +++ b/src/app/(main)/layout.tsx @@ -1,12 +1,13 @@ -import FooterWrapper from '@/shared/components/footer/FooterWrapper'; import Header from '@/shared/components/header/Header'; function NoLayout({ children }: { children: React.ReactNode }) { return ( <> -
+
{children}
- ); } diff --git a/src/domains/main/cocktailDrop/CocktailDrop.tsx b/src/domains/main/cocktailDrop/CocktailDrop.tsx index 216f994..8c399ea 100644 --- a/src/domains/main/cocktailDrop/CocktailDrop.tsx +++ b/src/domains/main/cocktailDrop/CocktailDrop.tsx @@ -44,11 +44,23 @@ function CocktailDrop({ isDesktop = false }: CocktailDropProps) { ); // 로고 위에서 아래로 자연스럽게 등장 + const screenWidth = window.innerWidth; + const viewportHeight = window.innerHeight; + const isTablet = screenWidth >= 640 && screenWidth < 1024; + const isMobile = screenWidth < 640; + + // 뷰포트 높이 기반으로 로고 위치 계산 + const logoFinalY = isMobile + ? `-${viewportHeight * 0.3}px` + : isTablet + ? `-${viewportHeight * -0.8}px` + : '0px'; + gsap.fromTo( logoRef.current, { y: -300, opacity: 0 }, { - y: !isDesktop ? -230 : -18, // 데스크톱이 아닐 때 더 위로 + y: logoFinalY, // 뷰포트 높이 기반 계산 opacity: 1, duration: 3, ease: 'power3.out', @@ -69,7 +81,7 @@ function CocktailDrop({ isDesktop = false }: CocktailDropProps) { return (
{/* 대각선 줄 1 */} @@ -84,7 +96,7 @@ function CocktailDrop({ isDesktop = false }: CocktailDropProps) { /> {/* 로고 */} -
+
로고 이미지
-
- {/* 컵 이미지 - 모바일에서 바닥에 붙도록 */} -
+
칵테일 컵
-
+
diff --git a/src/domains/main/components/3d/HomeLogo.tsx b/src/domains/main/components/3d/HomeLogo.tsx index b80a870..6ad77a4 100644 --- a/src/domains/main/components/3d/HomeLogo.tsx +++ b/src/domains/main/components/3d/HomeLogo.tsx @@ -3,8 +3,8 @@ import Image from 'next/image'; function HomeLogo({ isDesktop }: { isDesktop: boolean }) { return (
로고 이미지
diff --git a/src/domains/main/components/3d/HomeModel.tsx b/src/domains/main/components/3d/HomeModel.tsx index de0eac9..0e9e821 100644 --- a/src/domains/main/components/3d/HomeModel.tsx +++ b/src/domains/main/components/3d/HomeModel.tsx @@ -42,8 +42,8 @@ function Model({ onLoaded }: Props) { return ( ); diff --git a/src/domains/main/components/3d/HomeText.tsx b/src/domains/main/components/3d/HomeText.tsx index 64ec5f4..0a3fab9 100644 --- a/src/domains/main/components/3d/HomeText.tsx +++ b/src/domains/main/components/3d/HomeText.tsx @@ -2,8 +2,9 @@ function HomeText({ isDesktop }: { isDesktop: boolean }) { return ( <> {!isDesktop ? ( -

- 어떤 칵테일이 끌리시나요? SSoul이 쉽게 골라드릴게요. +

+ 어떤 칵테일이 끌리시나요?
+ SSoul이 쉽게 골라드릴게요.

) : (

diff --git a/src/domains/main/components/3d/ModelImage.tsx b/src/domains/main/components/3d/ModelImage.tsx index f6a4ddf..d556432 100644 --- a/src/domains/main/components/3d/ModelImage.tsx +++ b/src/domains/main/components/3d/ModelImage.tsx @@ -19,7 +19,7 @@ function ModelImage({ onLoaded }: Props) { width={260} height={290} priority - className="object-cover w-[300px] h-[390px]" + className="object-cover w-[300px] h-[350px]" />

diff --git a/src/domains/main/components/3d/StarMain.tsx b/src/domains/main/components/3d/StarMain.tsx index 5f18189..d212331 100644 --- a/src/domains/main/components/3d/StarMain.tsx +++ b/src/domains/main/components/3d/StarMain.tsx @@ -14,6 +14,10 @@ function StarMain() { useEffect(() => { if (!background.current || !foreground.current) return; + // 모바일에서는 별 애니메이션 비활성화 + const isMobile = window.innerWidth < 768; + if (isMobile) return; + const bgX = gsap.quickSetter(background.current, 'x', 'px'); const bgY = gsap.quickSetter(background.current, 'y', 'px'); const bgRotate = gsap.quickSetter(background.current, 'rotate', 'deg'); @@ -43,20 +47,11 @@ function StarMain() { mouse.current = { x, y }; }; - const handleTouchMove = (e: TouchEvent) => { - const touch = e.touches[0]; - const x = (touch.clientX / window.innerWidth - 0.5) * 2; - const y = (touch.clientY / window.innerHeight - 0.5) * 2; - mouse.current = { x, y }; - }; - window.addEventListener('mousemove', handleMouseMove); - window.addEventListener('touchmove', handleTouchMove); rafId.current = requestAnimationFrame(update); return () => { window.removeEventListener('mousemove', handleMouseMove); - window.removeEventListener('touchmove', handleTouchMove); if (rafId.current) cancelAnimationFrame(rafId.current); }; }, []); diff --git a/src/domains/mypage/components/pages/my-active/MyLike.tsx b/src/domains/mypage/components/pages/my-active/MyLike.tsx index 5f28325..216abd4 100644 --- a/src/domains/mypage/components/pages/my-active/MyLike.tsx +++ b/src/domains/mypage/components/pages/my-active/MyLike.tsx @@ -20,6 +20,10 @@ function MyLike() { fetchLike(); }, []); + useEffect(() => { + console.log(myLike); + }, [myLike]); + return (
{myLike.length > 0 ? ( diff --git a/src/domains/shared/components/3d/HomeBackground.tsx b/src/domains/shared/components/3d/HomeBackground.tsx deleted file mode 100644 index 0f45736..0000000 --- a/src/domains/shared/components/3d/HomeBackground.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { useEffect, useRef } from 'react'; - -function HomeBackground() { - const bgRef = useRef(null); - - useEffect(() => { - const handleMouseMove = (e: MouseEvent) => { - const x = e.clientX / window.innerWidth; - const percentage = 6 + x * 70; - if (bgRef.current) { - bgRef.current.style.background = `linear-gradient(128deg, rgba(26, 26, 26, 0.7) ${percentage}%, rgba(42, 42, 42, 0.3) ${percentage + 10}%, rgba(60, 70, 78, 0) 100%)`; - } - }; - - window.addEventListener('mousemove', handleMouseMove); - return () => window.removeEventListener('mousemove', handleMouseMove); - }, []); - - return ( -
- ); -} - -export default HomeBackground; diff --git a/src/domains/shared/components/3d/HomeModel.tsx b/src/domains/shared/components/3d/HomeModel.tsx deleted file mode 100644 index 4d0f3bc..0000000 --- a/src/domains/shared/components/3d/HomeModel.tsx +++ /dev/null @@ -1,96 +0,0 @@ -'use client'; - -import { Environment, OrbitControls, useGLTF } from '@react-three/drei'; -import { Canvas, useFrame, useThree } from '@react-three/fiber'; -import { Bloom, EffectComposer } from '@react-three/postprocessing'; -import { useEffect, useRef, useState } from 'react'; -import * as THREE from 'three'; - -function Model({ onLoaded }: { onLoaded: () => void }) { - const { scene } = useGLTF('/3d/model/scene.gltf'); - const [scale, setScale] = useState(13); - - useEffect(() => { - const isMobile = window.innerWidth < 768; // 모바일 기준 너비 - setScale(isMobile ? 3.8 : 11.5); // 모바일이면 작게 - }, []); - - useEffect(() => { - if (scene) { - onLoaded(); // 모델이 로드되면 부모에게 알림 - } - }, [scene]); - - if (!scene) return null; // 로딩 전 대기 처리 - - scene.traverse((child) => { - if ((child as THREE.Mesh).isMesh) { - const mesh = child as THREE.Mesh; - const material = mesh.material as THREE.MeshPhysicalMaterial; - - material.envMapIntensity = 3; - material.metalness = 1; - material.roughness = 0.3; - material.emissiveIntensity = 2; - material.clearcoat = 1; - material.clearcoatRoughness = 0.2; - material.needsUpdate = true; - material.opacity = 0.35; - material.bumpScale = 0.3; - material.thickness = 0.1; - } - }); - - return ; -} - -function CameraAnimation() { - const { camera } = useThree(); - const targetPosition = new THREE.Vector3(5, 10, 10); // 최종 위치 - const startPosition = new THREE.Vector3(0, 15, 6); // 시작 위치 - const progress = useRef(0); - - useFrame((state, delta) => { - if (progress.current < 1) { - progress.current += delta / 5; // 3초 동안 - const t = Math.min(progress.current, 1); - camera.position.lerpVectors(startPosition, targetPosition, t); - } - }); - - return null; -} - -function HomeModel({ onLoaded }: { onLoaded: () => void }) { - return ( - - - - - - - - - - - - - - - ); -} - -export default HomeModel; diff --git a/src/domains/shared/components/3d/Landing.tsx b/src/domains/shared/components/3d/Landing.tsx deleted file mode 100644 index ceded71..0000000 --- a/src/domains/shared/components/3d/Landing.tsx +++ /dev/null @@ -1,24 +0,0 @@ -'use client'; - -import { useState } from 'react'; -import HomeModel from './HomeModel'; -import StarMain from './StarMain'; -import Spinner from '@/shared/components/spinner/Spinner'; - -function Landing() { - const [isLoading, setIsLoading] = useState(true); - - return ( - <> - {isLoading && } -
-
- setIsLoading(false)} /> - {!isLoading && } -
-
- - ); -} - -export default Landing; diff --git a/src/domains/shared/components/3d/StarMain.tsx b/src/domains/shared/components/3d/StarMain.tsx deleted file mode 100644 index 87a00d9..0000000 --- a/src/domains/shared/components/3d/StarMain.tsx +++ /dev/null @@ -1,102 +0,0 @@ -'use client'; - -import Image from 'next/image'; -import foreStar from '../../../../../public/1Stars.png'; -import backStar from '../../../../../public/2Stars.png'; -import { useEffect, useRef } from 'react'; -import gsap from 'gsap'; - -function StarMain() { - const background = useRef(null); - const foreground = useRef(null); - const mouse = useRef({ x: 0, y: 0 }); - const rafId = useRef(null); - - useEffect(() => { - if (!background.current || !foreground.current) return; - - const bgX = gsap.quickSetter(background.current, 'x', 'px'); - const bgY = gsap.quickSetter(background.current, 'y', 'px'); - const bgRotate = gsap.quickSetter(background.current, 'rotate', 'deg'); - - const fgX = gsap.quickSetter(foreground.current, 'x', 'px'); - const fgY = gsap.quickSetter(foreground.current, 'y', 'px'); - const fgRotate = gsap.quickSetter(foreground.current, 'rotate', 'deg'); - - const update = () => { - const { x, y } = mouse.current; - - bgX(x * -2); - bgY(y * -2); - bgRotate(x * -0.2); - - fgX(x * 3); - fgY(y * 3); - fgRotate(y * 0.2); - - rafId.current = requestAnimationFrame(update); - }; - - const handleMouseMove = (e: MouseEvent) => { - // 화면 중앙 기준으로 얼마나 벗어났는지 (-1 ~ 1 범위) - const x = (e.clientX / window.innerWidth - 0.5) * 2; - const y = (e.clientY / window.innerHeight - 0.5) * 2; - mouse.current = { x, y }; - }; - - const handleTouchMove = (e: TouchEvent) => { - const touch = e.touches[0]; - const x = (touch.clientX / window.innerWidth - 0.5) * 2; - const y = (touch.clientY / window.innerHeight - 0.5) * 2; - mouse.current = { x, y }; - }; - - window.addEventListener('mousemove', handleMouseMove); - window.addEventListener('touchmove', handleTouchMove); - rafId.current = requestAnimationFrame(update); - - return () => { - window.removeEventListener('mousemove', handleMouseMove); - window.removeEventListener('touchmove', handleTouchMove); - if (rafId.current) cancelAnimationFrame(rafId.current); - }; - }, []); - - return ( - <> - {/* */} -
-
-
- 앞쪽 별 -
-
- 뒤쪽 별 -
-
-
- - ); -} - -export default StarMain; diff --git a/src/shared/components/header/DropdownMenu.tsx b/src/shared/components/header/DropdownMenu.tsx index 45c31ab..3e531fb 100644 --- a/src/shared/components/header/DropdownMenu.tsx +++ b/src/shared/components/header/DropdownMenu.tsx @@ -58,6 +58,7 @@ function DropdownMenu({ isClicked, setIsClicked, visible, setVisible }: Props) { } if (isClicked) { + window.scrollTo({ top: 0, behavior: 'smooth' }); setVisible(true); tlRef.current.play(); } else { diff --git a/src/shared/components/header/Header.tsx b/src/shared/components/header/Header.tsx index 164ae3b..b6e1b90 100644 --- a/src/shared/components/header/Header.tsx +++ b/src/shared/components/header/Header.tsx @@ -9,11 +9,17 @@ import { useEffect, useState } from 'react'; import tw from '@/shared/utills/tw'; import { useWindowScroll } from 'react-use'; -function Header({ className }: { className?: string }) { +interface Props { + className?: string; + isMain?: boolean; +} + +function Header({ className, isMain = false }: Props) { const pathname = usePathname(); const [showShadow, setShowShadow] = useState(true); const [lastScrollTop, setLastScrollTop] = useState(0); // 마지막 스크롤 위치 저장 const [visible, setVisible] = useState(true); + const [scrollDirection, setScrollDirection] = useState<'up' | 'down' | 'none'>('none'); const { y } = useWindowScroll(); @@ -25,15 +31,18 @@ function Header({ className }: { className?: string }) { // 유저가 아래로 스크롤 -> 헤더 숨기기 setVisible(false); setShowShadow(false); + setScrollDirection('down'); } else if (diff < 0) { // 유저가 위로 스크롤 -> 헤더 다시 보이기 setVisible(true); setShowShadow(true); + setScrollDirection('up'); } if (y <= 10) { setVisible(true); setShowShadow(false); + setScrollDirection('none'); return; } @@ -44,12 +53,16 @@ function Header({ className }: { className?: string }) {
10 ? 'bg-primary!' : 'bg-transparent') : 'bg-primary', + // 메인 페이지에서는 위로 스크롤할 때만 쉐도우 적용 + isMain + ? y > 10 && scrollDirection === 'up' + ? 'shadow-header' + : '' + : showShadow && 'shadow-header', className - ? className - : [ - 'bg-primary w-full h-[44px] md:h-[60px] flex items-center justify-between px-[12px] fixed top-0 left-0 z-50 transition-transform duration-200 ease-in-out', - showShadow && 'shadow-header', - ] )} >