인트로 화면: 타이틀 일러스트 + 구름 걷힘 연출
- 접속 시 intro.png 타이틀 화면, 중앙 하단 둥실거리는 시작하기 버튼 - 시작하기 클릭: 인트로가 1초간 투명해지며 아래 깔린 구름 레이어가 드러나고, 구름 두 장이 양옆으로 1.9초간 걷히며 마을 진입 - 구름은 CSS로 구성 (블러 처리한 본체 + 안쪽 가장자리 뭉게 퍼프 7개) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
이 커밋은 다음에 포함됨:
@@ -0,0 +1,81 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
|
||||
const LEAVE_MS = 2300; // 연출 총 길이 (인트로 페이드 + 구름 걷힘)
|
||||
|
||||
// 구름 안쪽 가장자리의 뭉게 퍼프 (top%, size(vh), edgeOffset(%))
|
||||
const PUFFS: Array<[number, number, number]> = [
|
||||
[-4, 26, -8],
|
||||
[12, 34, -3],
|
||||
[30, 28, -10],
|
||||
[46, 38, -2],
|
||||
[63, 30, -9],
|
||||
[78, 36, -4],
|
||||
[92, 27, -8],
|
||||
];
|
||||
|
||||
function CloudHalf({ side }: { side: "left" | "right" }) {
|
||||
return (
|
||||
<div className={`intro-cloud intro-cloud-${side}`}>
|
||||
{/* 구름 본체 */}
|
||||
<div className="absolute inset-0 bg-white" style={{ filter: "blur(10px)" }} />
|
||||
{/* 안쪽 가장자리 뭉게뭉게 */}
|
||||
{PUFFS.map(([top, size, off], i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="cloud-puff"
|
||||
style={{
|
||||
top: `${top}%`,
|
||||
[side === "left" ? "right" : "left"]: `${off}%`,
|
||||
width: `${size}vh`,
|
||||
height: `${size * 0.72}vh`,
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
/** 시작 화면: 타이틀 일러스트 + 시작하기 → 구름이 걷히며 마을 진입 */
|
||||
export default function IntroScreen({ onDone }: { onDone: () => void }) {
|
||||
const [leaving, setLeaving] = useState(false);
|
||||
|
||||
const start = () => {
|
||||
if (leaving) return;
|
||||
setLeaving(true);
|
||||
setTimeout(onDone, LEAVE_MS);
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`fixed inset-0 z-[100] overflow-hidden ${leaving ? "intro-leaving pointer-events-none" : ""}`}
|
||||
>
|
||||
{/* 구름 레이어 (인트로 아래) — 인트로가 투명해지면 드러나고, 양옆으로 걷힘 */}
|
||||
<CloudHalf side="left" />
|
||||
<CloudHalf side="right" />
|
||||
|
||||
{/* 타이틀 일러스트 */}
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img
|
||||
src="/assets/intro.png"
|
||||
alt="고양이 마을"
|
||||
className="absolute inset-0 h-full w-full object-cover transition-opacity duration-1000 ease-out"
|
||||
style={{ opacity: leaving ? 0 : 1 }}
|
||||
/>
|
||||
|
||||
{/* 시작하기 버튼 */}
|
||||
<div
|
||||
className="absolute inset-x-0 bottom-[16%] flex justify-center transition-opacity duration-500"
|
||||
style={{ opacity: leaving ? 0 : 1 }}
|
||||
>
|
||||
<button
|
||||
onClick={start}
|
||||
className="nature-btn animate-bounce-slow px-12 py-4 text-2xl shadow-2xl"
|
||||
>
|
||||
🐾 시작하기
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
새 이슈에서 참조
사용자 차단