feat: Add planet markers to IslandUniverse map

- Display planets as ringed spheres in outer ring
- Add getPlanetColor helper for planet themes
- Planet markers show name and member count
- Click handler ready for future navigation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Your Name 2026-01-24 07:49:55 +00:00
parent 7faf0b180b
commit 5ffec6bcec
1 changed files with 86 additions and 0 deletions

View File

@ -185,6 +185,76 @@ export default function IslandUniverse({ onClose, onIslandClick }) {
markers.push({ marker, island, el }); markers.push({ marker, island, el });
}); });
// Add planet markers (positioned in outer ring)
planets.forEach((planet, idx) => {
const angle = (idx / Math.max(planets.length, 1)) * Math.PI * 2;
const radius = 18 + (idx % 3) * 4;
const lng = centerLng + Math.cos(angle) * radius;
const lat = centerLat + Math.sin(angle) * radius;
const el = document.createElement('div');
el.className = 'universe-planet-marker';
const planetColor = getPlanetColor(planet.theme || 'default');
const memberCount = planet.member_count || 0;
el.innerHTML = `
<div class="universe-planet-shape" style="
position: relative;
cursor: pointer;
transition: all 0.4s ease;
animation: universePlanetOrbit 12s linear infinite;
filter: drop-shadow(0 0 25px ${planetColor}99);
">
<svg width="100" height="100" viewBox="0 0 100 100">
<defs>
<radialGradient id="pg-${idx}" cx="35%" cy="35%">
<stop offset="0%" stop-color="${planetColor}" />
<stop offset="100%" stop-color="${planetColor}" stop-opacity="0.6" />
</radialGradient>
</defs>
<ellipse cx="50" cy="50" rx="45" ry="12" fill="none" stroke="${planetColor}" stroke-width="3" opacity="0.5" transform="rotate(-20 50 50)"/>
<circle cx="50" cy="50" r="30" fill="url(#pg-${idx})"/>
</svg>
<div style="
position: absolute;
bottom: -30px;
left: 50%;
transform: translateX(-50%);
background: rgba(20, 10, 40, 0.95);
color: white;
padding: 6px 12px;
border-radius: 12px;
font-size: 11px;
font-weight: 700;
white-space: nowrap;
border: 1px solid ${planetColor}66;
">
<span style="color: ${planetColor};">🪐 ${planet.name || 'Planet'}</span>
<span style="font-size: 9px; color: rgba(255,255,255,0.6); display: block;">
${memberCount} ${t('universe.members')}
</span>
</div>
</div>
`;
el.addEventListener('mouseenter', () => {
setHoveredIsland({ ...planet, isPlanet: true, username: planet.name });
});
el.addEventListener('mouseleave', () => setHoveredIsland(null));
el.addEventListener('click', (e) => {
e.stopPropagation();
console.log('[IslandUniverse] Clicked planet:', planet.name);
// TODO: Navigate to planet page when ready
});
const marker = new maplibregl.Marker({ element: el, anchor: 'center' })
.setLngLat([lng, lat])
.addTo(map);
markers.push({ marker, planet, el, isPlanet: true });
});
markersRef.current = markers; markersRef.current = markers;
// Slow rotation animation // Slow rotation animation
@ -328,6 +398,22 @@ function getTerrainColor(terrainType) {
return palettes[terrainType] || palettes['tropical']; return palettes[terrainType] || palettes['tropical'];
} }
/**
* Get planet theme color
*/
function getPlanetColor(theme) {
const palettes = {
'default': '#9b59b6',
'tech': '#3498db',
'gaming': '#e74c3c',
'music': '#1abc9c',
'art': '#e91e63',
'science': '#00bcd4',
'sports': '#ff9800',
};
return palettes[theme] || palettes['default'];
}
/** /**
* Generate a detailed island SVG shape (bigger, more features) * Generate a detailed island SVG shape (bigger, more features)
*/ */