This commit is contained in:
암냥 2026-03-06 22:30:35 +09:00
commit 991bc55102
No known key found for this signature in database
4 changed files with 69 additions and 17 deletions

BIN
public/audio.opus Normal file

Binary file not shown.

BIN
public/window-nadae.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

View file

@ -6,7 +6,10 @@ import ReadmeWindow from "@/components/ReadmeWindow";
import Contact from "@/components/Contact"; import Contact from "@/components/Contact";
import DDayComponent from "@/components/dday"; import DDayComponent from "@/components/dday";
export default function Page() { export default async function Page({ searchParams }: { searchParams: Promise<{ nowindow?: string }> }) {
const params = await searchParams;
const showWindow = params.nowindow === undefined;
return ( return (
<main className="min-h-screen w-screen overflow-y-scroll snap-y snap-mandatory relative"> <main className="min-h-screen w-screen overflow-y-scroll snap-y snap-mandatory relative">
<div className="max-w-3xl w-full flex flex-row h-auto mx-auto my-8 items-center justify-between lg:px-0 px-8"> <div className="max-w-3xl w-full flex flex-row h-auto mx-auto my-8 items-center justify-between lg:px-0 px-8">
@ -28,7 +31,7 @@ export default function Page() {
<Contact /> <Contact />
</div> </div>
<section id="about" className="w-full snap-start snap-always flex flex-col items-center justify-center px-8 lg:px-0"> <section id="about" className="w-full snap-start snap-always flex flex-col items-center justify-center px-8 lg:px-0">
<DraggableWindow /> {showWindow && <DraggableWindow />}
<div className="max-w-3xl w-full lg:px-0 px-8"> <div className="max-w-3xl w-full lg:px-0 px-8">
<p><strong> </strong> .</p> <p><strong> </strong> .</p>
<p><strong> </strong> , .</p> <p><strong> </strong> , .</p>

View file

@ -10,7 +10,10 @@ export default function DraggableWindow() {
const [position, setPosition] = useState({ x: 100, y: 100 }); const [position, setPosition] = useState({ x: 100, y: 100 });
const [isDragging, setIsDragging] = useState(false); const [isDragging, setIsDragging] = useState(false);
const [dragOffset, setDragOffset] = useState({ x: 0, y: 0 }); const [dragOffset, setDragOffset] = useState({ x: 0, y: 0 });
const [isNadaeVisible, setIsNadaeVisible] = useState(false);
const windowRef = useRef<HTMLDivElement>(null); const windowRef = useRef<HTMLDivElement>(null);
const audioRef = useRef<HTMLAudioElement | null>(null);
const nadaeTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
const handleMouseDown = (e: React.MouseEvent) => { const handleMouseDown = (e: React.MouseEvent) => {
setIsDragging(true); setIsDragging(true);
@ -23,6 +26,26 @@ export default function DraggableWindow() {
} }
}; };
const handleActivate = () => {
if (!audioRef.current) {
audioRef.current = new Audio('/audio.opus');
}
audioRef.current.currentTime = 0;
void audioRef.current.play();
setIsNadaeVisible(true);
if (nadaeTimeoutRef.current) {
clearTimeout(nadaeTimeoutRef.current);
}
nadaeTimeoutRef.current = setTimeout(() => {
setIsNadaeVisible(false);
nadaeTimeoutRef.current = null;
}, 1000);
};
useEffect(() => { useEffect(() => {
const handleMouseMove = (e: MouseEvent) => { const handleMouseMove = (e: MouseEvent) => {
if (!isDragging) return; if (!isDragging) return;
@ -48,12 +71,27 @@ export default function DraggableWindow() {
}; };
}, [isDragging, dragOffset]); }, [isDragging, dragOffset]);
useEffect(() => {
return () => {
audioRef.current?.pause();
audioRef.current = null;
if (nadaeTimeoutRef.current) {
clearTimeout(nadaeTimeoutRef.current);
}
};
}, []);
return ( return (
isMobile ? ( isMobile ? (
<figure className="mb-8 w-full h-auto"> <figure className="mb-8 w-full h-auto">
<button
type="button"
className="block w-full rounded-xl text-left"
>
<picture className="block bg-gray-100 rounded-xl aspect-3-2 overflow-hidden image-scale object-shadowed"> <picture className="block bg-gray-100 rounded-xl aspect-3-2 overflow-hidden image-scale object-shadowed">
<Image <Image
src="/full.webp" src={'/full.webp'}
alt="Banner" alt="Banner"
width={1200} width={1200}
height={400} height={400}
@ -61,21 +99,21 @@ export default function DraggableWindow() {
className="object-cover object-center transition-transform duration-300 hover:scale-105" className="object-cover object-center transition-transform duration-300 hover:scale-105"
/> />
</picture> </picture>
</button>
</figure > </figure >
) : ( ) : (
isVisible && ( isVisible && (
<div <div
ref={windowRef} ref={windowRef}
className="fixed cursor-move select-none" className="fixed cursor-pointer select-none"
style={{ style={{
left: `${position.x}px`, left: `${position.x}px`,
top: `${position.y}px`, top: `${position.y}px`,
}} }}
onMouseDown={handleMouseDown}
> >
<div className="relative w-fit h-fit"> <div className="relative w-fit h-fit">
<Image <Image
src="/window.webp" src={isNadaeVisible ? '/image.png' : '/window.webp'}
alt="Draggable Window" alt="Draggable Window"
width={500} width={500}
height={400} height={400}
@ -83,8 +121,19 @@ export default function DraggableWindow() {
draggable={false} draggable={false}
/> />
<button <button
onClick={() => setIsVisible(false)} type="button"
className="absolute top-1 right-2 w-5 h-5 cursor-pointer" onMouseDown={handleMouseDown}
onClick={handleActivate}
className="absolute inset-0 cursor-pointer"
aria-label="Play audio"
/>
<button
type="button"
onClick={(e) => {
e.stopPropagation();
setIsVisible(false);
}}
className="absolute top-1 right-2 z-10 w-5 h-5 cursor-pointer"
aria-label="Close window" aria-label="Close window"
/> />
</div> </div>