Spaces:
Running
Running
Upload 8 files
Browse files- src/views/InstructorView.js +38 -20
src/views/InstructorView.js
CHANGED
|
@@ -211,12 +211,14 @@ export function setupInstructorEvents() {
|
|
| 211 |
<img src="assets/instructor_avatar.png" class="relative w-48 h-48 md:w-64 md:h-64 object-contain pixel-art drop-shadow-[0_10px_30px_rgba(0,0,0,0.6)] z-10 hover:scale-105 transition-transform duration-300" alt="Instructor">
|
| 212 |
|
| 213 |
<!-- Editable Name Tag -->
|
| 214 |
-
<div class="absolute -bottom-8 left-1/2 transform -translate-x-1/2 bg-black/80 backdrop-blur text-yellow-400 px-6 py-2 rounded-full border border-yellow-500/30 shadow-2xl flex items-center space-x-2 z-30 whitespace-nowrap group-hover:bg-black transition-colors">
|
| 215 |
<span class="text-xl">👑</span>
|
| 216 |
<input type="text" id="instructor-name-input"
|
| 217 |
value="${savedName}"
|
| 218 |
-
class="bg-transparent border-b border-transparent hover:border-yellow-500/50 focus:border-yellow-500 text-lg font-bold text-yellow-400 text-center focus:outline-none
|
|
|
|
| 219 |
onclick="this.select()"
|
|
|
|
| 220 |
>
|
| 221 |
</div>
|
| 222 |
</div>
|
|
@@ -245,47 +247,63 @@ export function setupInstructorEvents() {
|
|
| 245 |
const monster = getNextMonster(s.monster_stage || 0, totalLikes, total, s.monster_id);
|
| 246 |
|
| 247 |
// Scatter Logic: Radial Distribution with Jitter
|
| 248 |
-
// Min radius
|
| 249 |
-
const minR =
|
| 250 |
-
const maxR =
|
| 251 |
|
| 252 |
// Angle: Evenly distributed + Jitter
|
| 253 |
-
|
| 254 |
-
const angleJitter = (Math.random() - 0.5) * 0.5;
|
| 255 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 256 |
|
| 257 |
// Radius: Random within range
|
| 258 |
const radius = minR + Math.random() * (maxR - minR);
|
| 259 |
|
| 260 |
-
// Convert to % for responsiveness (Relative to center 50%)
|
| 261 |
-
// Assuming container ~800px wide, 50% = 400px.
|
| 262 |
-
// x offset = cos(angle) * r
|
| 263 |
const xOff = Math.cos(finalAngle) * radius;
|
| 264 |
-
const yOff = Math.sin(finalAngle) * radius * 0.8;
|
| 265 |
|
| 266 |
const card = document.createElement('div');
|
| 267 |
card.className = 'absolute flex flex-col items-center group/card z-10 hover:z-50 transition-all duration-500';
|
| 268 |
|
| 269 |
-
// Style placement
|
| 270 |
card.style.left = `calc(50% + ${xOff}px)`;
|
| 271 |
card.style.top = `calc(50% + ${yOff}px)`;
|
| 272 |
-
card.style.transform = 'translate(-50%, -50%)';
|
| 273 |
|
| 274 |
-
// Add slight floating animation delay
|
| 275 |
const floatDelay = Math.random() * 2;
|
| 276 |
|
| 277 |
card.innerHTML = `
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 278 |
<div class="relative w-20 h-20 md:w-24 md:h-24 flex items-center justify-center transform group-hover/card:scale-125 transition-transform duration-300" style="animation: float 3s ease-in-out infinite; animation-delay: -${floatDelay}s;">
|
| 279 |
<div class="w-full h-full pixel-art drop-shadow-md filter group-hover/card:brightness-110 transition-all">
|
| 280 |
${generateMonsterSVG(monster)}
|
| 281 |
</div>
|
| 282 |
-
<div class="absolute -top-4 -right-2 opacity-0 group-hover/card:opacity-100 transition-opacity text-pink-400 text-lg font-bold animate-bounce hidden md:block">
|
| 283 |
-
❤️
|
| 284 |
-
</div>
|
| 285 |
</div>
|
| 286 |
|
| 287 |
-
<
|
| 288 |
-
|
|
|
|
| 289 |
</div>
|
| 290 |
`;
|
| 291 |
relativeContainer.appendChild(card);
|
|
|
|
| 211 |
<img src="assets/instructor_avatar.png" class="relative w-48 h-48 md:w-64 md:h-64 object-contain pixel-art drop-shadow-[0_10px_30px_rgba(0,0,0,0.6)] z-10 hover:scale-105 transition-transform duration-300" alt="Instructor">
|
| 212 |
|
| 213 |
<!-- Editable Name Tag -->
|
| 214 |
+
<div class="absolute -bottom-8 left-1/2 transform -translate-x-1/2 bg-black/80 backdrop-blur text-yellow-400 px-6 py-2 rounded-full border border-yellow-500/30 shadow-2xl flex items-center justify-center space-x-2 z-30 whitespace-nowrap group-hover:bg-black transition-colors min-w-[150px] max-w-[300px]">
|
| 215 |
<span class="text-xl">👑</span>
|
| 216 |
<input type="text" id="instructor-name-input"
|
| 217 |
value="${savedName}"
|
| 218 |
+
class="bg-transparent border-b border-transparent hover:border-yellow-500/50 focus:border-yellow-500 text-lg font-bold text-yellow-400 text-center focus:outline-none transition-all placeholder-yellow-700"
|
| 219 |
+
style="width: ${Math.max(savedName.length * 20, 100)}px;"
|
| 220 |
onclick="this.select()"
|
| 221 |
+
oninput="this.style.width = Math.max(this.value.length * 20, 100) + 'px'"
|
| 222 |
>
|
| 223 |
</div>
|
| 224 |
</div>
|
|
|
|
| 247 |
const monster = getNextMonster(s.monster_stage || 0, totalLikes, total, s.monster_id);
|
| 248 |
|
| 249 |
// Scatter Logic: Radial Distribution with Jitter
|
| 250 |
+
// Min radius increased to verify clearance around label
|
| 251 |
+
const minR = 220;
|
| 252 |
+
const maxR = 350;
|
| 253 |
|
| 254 |
// Angle: Evenly distributed + Jitter
|
| 255 |
+
let baseAngle = (index / total) * 2 * Math.PI;
|
| 256 |
+
const angleJitter = (Math.random() - 0.5) * 0.5;
|
| 257 |
+
let finalAngle = baseAngle + angleJitter;
|
| 258 |
+
|
| 259 |
+
// Collision Avoidance for Bottom Label (approx 90 deg / PI/2)
|
| 260 |
+
// If angle is roughly downwards (e.g., between 80deg and 100deg), push it aside
|
| 261 |
+
const deg = finalAngle * (180 / Math.PI) % 360;
|
| 262 |
+
const normalizedDeg = deg < 0 ? deg + 360 : deg;
|
| 263 |
+
|
| 264 |
+
// Avoid "South" (approx 75 to 105 degrees) where the label sticks out
|
| 265 |
+
if (normalizedDeg > 75 && normalizedDeg < 105) {
|
| 266 |
+
finalAngle += (Math.random() > 0.5 ? 0.5 : -0.5); // Push left or right by ~30 deg
|
| 267 |
+
}
|
| 268 |
|
| 269 |
// Radius: Random within range
|
| 270 |
const radius = minR + Math.random() * (maxR - minR);
|
| 271 |
|
|
|
|
|
|
|
|
|
|
| 272 |
const xOff = Math.cos(finalAngle) * radius;
|
| 273 |
+
const yOff = Math.sin(finalAngle) * radius * 0.8;
|
| 274 |
|
| 275 |
const card = document.createElement('div');
|
| 276 |
card.className = 'absolute flex flex-col items-center group/card z-10 hover:z-50 transition-all duration-500';
|
| 277 |
|
|
|
|
| 278 |
card.style.left = `calc(50% + ${xOff}px)`;
|
| 279 |
card.style.top = `calc(50% + ${yOff}px)`;
|
| 280 |
+
card.style.transform = 'translate(-50%, -50%)';
|
| 281 |
|
|
|
|
| 282 |
const floatDelay = Math.random() * 2;
|
| 283 |
|
| 284 |
card.innerHTML = `
|
| 285 |
+
<!-- Top Info: Monster Stats -->
|
| 286 |
+
<div class="mb-1 text-center bg-gray-900/60 backdrop-blur-sm rounded-lg px-2 py-1 border border-gray-600/30 group-hover/card:bg-gray-800 group-hover/card:border-cyan-500/50 transition-all opacity-80 group-hover/card:opacity-100 transform translate-y-2 group-hover/card:translate-y-0 duration-300">
|
| 287 |
+
<div class="text-[10px] text-gray-300 mb-0.5 whitespace-nowrap">${monster.name.split(' ')[1] || monster.name}</div>
|
| 288 |
+
<div class="flex items-center justify-center space-x-2">
|
| 289 |
+
<span class="text-[10px] bg-blue-900/50 text-blue-300 px-1.5 rounded border border-blue-500/30">Lv.${(s.monster_stage || 0) + 1}</span>
|
| 290 |
+
<div class="flex items-center text-[10px] text-pink-400 font-bold">
|
| 291 |
+
<span>♥</span>
|
| 292 |
+
<span class="ml-0.5">${totalLikes}</span>
|
| 293 |
+
</div>
|
| 294 |
+
</div>
|
| 295 |
+
</div>
|
| 296 |
+
|
| 297 |
+
<!-- Monster Image -->
|
| 298 |
<div class="relative w-20 h-20 md:w-24 md:h-24 flex items-center justify-center transform group-hover/card:scale-125 transition-transform duration-300" style="animation: float 3s ease-in-out infinite; animation-delay: -${floatDelay}s;">
|
| 299 |
<div class="w-full h-full pixel-art drop-shadow-md filter group-hover/card:brightness-110 transition-all">
|
| 300 |
${generateMonsterSVG(monster)}
|
| 301 |
</div>
|
|
|
|
|
|
|
|
|
|
| 302 |
</div>
|
| 303 |
|
| 304 |
+
<!-- Bottom Info: User Nickname -->
|
| 305 |
+
<div class="mt-1 text-center bg-black/60 backdrop-blur-sm rounded-full px-3 py-0.5 border border-gray-600/50 group-hover/card:bg-cyan-900/80 group-hover/card:border-cyan-400 transition-all">
|
| 306 |
+
<div class="text-xs font-bold text-white shadow-black drop-shadow-md whitespace-nowrap tracking-wide">${s.nickname}</div>
|
| 307 |
</div>
|
| 308 |
`;
|
| 309 |
relativeContainer.appendChild(card);
|