1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
import React, { useEffect, useState, useRef } from 'react'
type Props = {
onComplete: () => void
}
export const LoadingScreen: React.FC<Props> = ({ onComplete }) => {
const [fadeOut, setFadeOut] = useState(false)
const [mounted, setMounted] = useState(true)
const [subtitle, setSubtitle] = useState('')
const [animatedText, setAnimatedText] = useState('')
const subtitleLoaded = useRef(false)
useEffect(() => {
console.log('Loading screen mounted - starting timer...')
// Set fixed subtitle and animate it
if (!subtitleLoaded.current) {
subtitleLoaded.current = true
const fixedSubtitle = 'Whisper of the Heart'
setSubtitle(fixedSubtitle)
// Animate text character by character
let currentIndex = 0
const animateText = () => {
if (currentIndex <= fixedSubtitle.length) {
setAnimatedText(fixedSubtitle.slice(0, currentIndex))
currentIndex++
setTimeout(animateText, 50) // 50ms delay between characters
}
}
// Start animation after heart appears (1000ms = 0.2s heart delay + 0.8s heart animation)
setTimeout(animateText, 1000)
}
// Start fade after 4 seconds (longer to show ray spinning)
const fadeTimer = setTimeout(() => {
console.log('4 seconds passed - Starting fade out...')
setFadeOut(true)
}, 4000)
// Complete after fade finishes (4s show + 1s fade = 5s total)
const completeTimer = setTimeout(() => {
console.log('5 seconds passed - Loading screen completing...')
setMounted(false)
onComplete()
}, 5000)
return () => {
console.log('Cleaning up timers...')
clearTimeout(fadeTimer)
clearTimeout(completeTimer)
}
}, []) // Empty dependency array - run once on mount
const handleClick = () => {
console.log('Loading screen clicked, completing early...')
setFadeOut(true)
setTimeout(() => {
setMounted(false)
onComplete()
}, 1000)
}
console.log('LoadingScreen render - fadeOut:', fadeOut, 'mounted:', mounted)
if (!mounted) return null
return (
<div className={`loading-screen ${fadeOut ? 'fade-out' : ''}`} onClick={handleClick}>
<div className="loading-logo">
<div className="heart-container">
<div className="sun-rays loading-animate-rays">
<svg viewBox="0 0 100 100" className="rays-svg">
{/* Rising Sun flag style rays - triangular rays extending to edges */}
<g transform="translate(50, 50)">
{[...Array(16)].map((_, i) => {
const angle = (i * 22.5);
const nextAngle = ((i + 1) * 22.5);
const rayWidth = 11.25; // Half the angle between rays for triangular shape
// Create triangular ray path
const startAngle = angle - rayWidth;
const endAngle = angle + rayWidth;
const innerRadius = 0; // Start from center (heart center)
const outerRadius = 70; // Extend to screen edge
const x1 = Math.cos(startAngle * Math.PI / 180) * innerRadius;
const y1 = Math.sin(startAngle * Math.PI / 180) * innerRadius;
const x2 = Math.cos(endAngle * Math.PI / 180) * innerRadius;
const y2 = Math.sin(endAngle * Math.PI / 180) * innerRadius;
const x3 = Math.cos(startAngle * Math.PI / 180) * outerRadius;
const y3 = Math.sin(startAngle * Math.PI / 180) * outerRadius;
const x4 = Math.cos(endAngle * Math.PI / 180) * outerRadius;
const y4 = Math.sin(endAngle * Math.PI / 180) * outerRadius;
return (
<polygon
key={i}
points={`${x1},${y1} ${x2},${y2} ${x4},${y4} ${x3},${y3}`}
fill={i % 2 === 0 ? "#8B0000" : "#000000"}
opacity="0.9"
/>
);
})}
</g>
</svg>
</div>
<div className="heart-outline loading-animate-heart">
<svg viewBox="0 0 100 100" className="heart-svg">
<path d="M50,85 C50,85 10,60 10,35 C10,18 20,8 35,8 C42,8 50,13 50,25 C50,13 58,8 65,8 C80,8 90,18 90,35 C90,60 50,85 50,85 Z"
fill="#8B0000"
stroke="#8B0000"
strokeWidth="2"/>
</svg>
</div>
<div className="logo-text loading-animate-text">soryu</div>
<div className="loading-subtitle loading-animate-subtitle">{animatedText}</div>
<div className="loading-dots loading-animate-text">
<span>.</span><span>.</span><span>.</span>
</div>
</div>
</div>
</div>
)
}
|