Implement 2D galaxy view

This commit is contained in:
Aelita4 2024-09-30 12:25:57 +02:00
parent 718a9b5da6
commit b51200f3e8
Signed by: Aelita4
GPG Key ID: E44490C2025906C1
1 changed files with 130 additions and 63 deletions

View File

@ -2,7 +2,6 @@
import Layout from '../../layouts/Layout.astro';
import NavBar from '../../components/NavBar.astro';
import { getUserByAccessToken } from '../../lib/db/users';
import { getAllPlanets } from '../../lib/db/planets';
import locationManager from '../../lib/classes/managers/LocationManager';
import ResourceBar from '../../components/ResourceBar.astro';
@ -13,89 +12,157 @@ if(loggedToken === null || username === "") return Astro.redirect('/logout');
const checkUser = await getUserByAccessToken(loggedToken);
if(checkUser === null || checkUser.username !== username) return Astro.redirect('/logout');
const allPlanets = await getAllPlanets();
const allGalaxies = locationManager.galaxies;
const formattedPlanets = allPlanets.map(planet => {
let i = 0;
const galaxies = allGalaxies.map(galaxy => {
return {
name: planet.name,
owner: locationManager.getUser(planet.owner)?.username ?? "Unowned"
numericId: i++,
name: galaxy.name,
style: {
left: 0,
top: 0,
color: "red"
},
sectors: galaxy.sectors.map(sector => {
return {
id: sector._id.toString(),
name: sector.name
};
})
};
})
for(const galaxy of galaxies) {
for(let i = 0; i < 100; i++) {
galaxy.style.left = Math.random() * 1200 + 20;
galaxy.style.top = Math.random() * 380 + 20;
const overlap = galaxies.slice(0, galaxy.numericId).some(otherGalaxy => {
const dx = galaxy.style.left - otherGalaxy.style.left;
const dy = galaxy.style.top - otherGalaxy.style.top;
const distance = Math.sqrt(dx * dx + dy * dy);
return distance < 100;
});
if(!overlap) {
galaxy.style.color = "white"
break;
}
}
}
---
<Layout title="Galaxy view">
<NavBar loggedIn="true" active="galaxyView" />
<ResourceBar />
<ul>
{formattedPlanets.map(planet => <li>{planet.name} ({planet.owner})</li>)}
</ul>
<div class="container">
<div class="galaxy-container">
{galaxies.map(galaxy => <>
<a href="#">
<div class="galaxy-icon" style={`left: ${galaxy.style.left}px; top: ${galaxy.style.top}px; background-color: ${galaxy.style.color};`}>
<div class="galaxy-name" data-sectors={JSON.stringify(galaxy.sectors)}>{galaxy.name}</div>
</div>
</a>
</>)}
</div>
<div class="galaxy-details">
<h2></h2>
<div class="galaxy-sector-list">
</div>
</div>
</div>
</Layout>
<style>
* {
<style is:global>
.container {
display: flex;
flex-direction: row;
color: white;
}
main {
margin: auto;
padding: 1rem;
width: 800px;
max-width: calc(100% - 2rem);
color: white;
font-size: 20px;
line-height: 1.6;
.galaxy-container {
width: 70%;
height: 500px;
background-color: blue;
margin-left: 50px;
margin-right: auto;
margin-top: 50px;
position: relative;
}
.astro-a {
.galaxy-icon {
position:absolute;
width: 40px;
height: 40px;
background-color: white;
border-radius: 20px;
}
.galaxy-icon:hover {
background-color: yellow !important;
}
.galaxy-name {
position: absolute;
top: -32px;
left: 50%;
transform: translatex(-50%);
width: 220px;
height: auto;
z-index: -1;
top: 40px;
left: -5px;
color: white;
}
h1 {
font-size: 4rem;
font-weight: 700;
line-height: 1;
.galaxy-details {
width: 23%;
height: 500px;
margin-top: 50px;
margin-right: 50px;
}
.galaxy-details h2 {
text-align: center;
margin-bottom: 1em;
}
.text-gradient {
background-image: var(--accent-gradient);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-size: 400%;
background-position: 0%;
.galaxy-sector-list {
display: flex;
flex-direction: column;
}
.instructions {
margin-bottom: 2rem;
border: 1px solid rgba(var(--accent-light), 25%);
background: linear-gradient(rgba(var(--accent-dark), 66%), rgba(var(--accent-dark), 33%));
padding: 1.5rem;
border-radius: 8px;
.galaxy-sector-list div {
text-align: center;
background-color: gray;
margin-top: 10px;
border-radius: 10px;
padding-top: 10px;
padding-bottom: 10px;
}
</style>
<script>
function gvinit() {
const galaxyIcons = document.querySelectorAll('.galaxy-icon');
const galaxyDetails = document.querySelector('.galaxy-details');
const galaxySectorList = document.querySelector('.galaxy-sector-list');
if(!galaxyIcons) return;
if(!galaxyDetails) return;
if(!galaxySectorList) return;
galaxyIcons.forEach(icon => {
icon.addEventListener('click', (e) => {
const galaxy = icon.querySelector('.galaxy-name');
if(!galaxy) return;
const sectors: Array<{ id: string, name: string }> = JSON.parse(galaxy.getAttribute('data-sectors') ?? "[]");
const galaxyNameField = galaxyDetails.querySelector('h2');
if(!galaxyNameField) return;
galaxyNameField.innerText = (icon.querySelector('.galaxy-name') as HTMLElement)?.innerText;
galaxySectorList.innerHTML = "";
sectors.forEach(sector => {
const sectorDiv = document.createElement('div');
sectorDiv.innerText = sector.name;
sectorDiv.setAttribute('data-id', sector.id);
galaxySectorList.appendChild(sectorDiv);
});
});
});
}
.instructions code {
font-size: 0.8em;
font-weight: bold;
background: rgba(var(--accent-light), 12%);
color: rgb(var(--accent-light));
border-radius: 4px;
padding: 0.3em 0.4em;
}
.instructions strong {
color: rgb(var(--accent-light));
}
.link-card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(24ch, 1fr));
gap: 2rem;
padding: 0;
}
</style>
gvinit();
</script>