Popups links erstellen

This commit is contained in:
Cay 2026-03-16 11:57:11 +00:00
parent c708609e7b
commit d7b895cd70
12 changed files with 1144 additions and 0 deletions

464
public/css/1v1.css Normal file

File diff suppressed because one or more lines are too long

242
public/css/quickmenu.css Normal file
View File

@ -0,0 +1,242 @@
/* =========================
Quick Menu Toggle Button
========================= */
#quickmenu-toggle {
position: fixed;
top: 16px;
left: 16px;
z-index: 2000;
width: 36px;
height: 36px;
background: rgba(20, 12, 4, 0.75);
border: 2px solid #8b6a3c;
border-radius: 6px;
color: #f0d9a6;
font-size: 18px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: 0.2s;
backdrop-filter: blur(4px);
}
#quickmenu-toggle:hover {
background: rgba(107, 75, 42, 0.85);
box-shadow: 0 0 10px rgba(200, 160, 60, 0.4);
}
/* =========================
Quick Menu Panel
========================= */
#quickmenu-panel {
position: fixed;
top: 60px;
left: 16px;
z-index: 1999;
display: grid;
grid-template-columns: repeat(3, 90px);
gap: 8px;
padding: 10px;
background: transparent;
transition: opacity 0.25s ease, transform 0.25s ease;
opacity: 1;
transform: translateX(0);
}
#quickmenu-panel.hidden {
opacity: 0;
transform: translateX(-120%);
pointer-events: none;
}
/* =========================
Einzelne Slots
========================= */
.qm-slot {
width: 90px;
height: 90px;
position: relative;
background: linear-gradient(145deg, #3a2810, #1a0f04);
border: 2px solid #8b6a3c;
border-radius: 10px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 4px;
cursor: pointer;
transition: 0.2s;
box-shadow:
0 4px 12px rgba(0, 0, 0, 0.6),
inset 0 1px 0 rgba(255, 220, 100, 0.08);
}
.qm-slot:hover {
border-color: #f0d060;
transform: scale(1.06);
box-shadow:
0 6px 20px rgba(0, 0, 0, 0.7),
0 0 12px rgba(200, 160, 60, 0.35);
}
.qm-slot:active {
transform: scale(0.97);
}
.qm-slot img {
width: 52px;
height: 52px;
object-fit: contain;
filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8));
}
.qm-slot-label {
font-family: "Cinzel", serif;
font-size: 9px;
font-weight: bold;
color: #e7d9b4;
text-align: center;
line-height: 1.2;
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.9);
padding: 0 4px;
}
/* Badge (z.B. Timer, Anzahl) */
.qm-badge {
position: absolute;
bottom: 5px;
right: 5px;
background: rgba(0, 0, 0, 0.7);
border: 1px solid #8b6a3c;
border-radius: 4px;
font-family: "Cinzel", serif;
font-size: 9px;
color: #ffd700;
padding: 1px 4px;
}
/* =========================
Quick Menu Popups
========================= */
.qm-popup {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) scale(0.9);
width: 1800px;
height: 1000px;
max-width: 98vw;
max-height: 96vh;
background: url("/images/parchment.png") center / cover no-repeat;
border: 4px solid #6b4b2a;
border-radius: 12px;
box-shadow:
0 0 60px rgba(0, 0, 0, 0.95),
inset 0 0 30px rgba(0, 0, 0, 0.4);
z-index: 3000;
display: none;
opacity: 0;
flex-direction: column;
transition: opacity 0.25s ease, transform 0.25s ease;
}
.qm-popup.active {
display: flex;
opacity: 1;
transform: translate(-50%, -50%) scale(1);
}
/* Popup Header */
.qm-popup-header {
padding: 14px 20px;
background: linear-gradient(#6b4b2a, #3c2414);
border-bottom: 2px solid #8b6a3c;
border-radius: 8px 8px 0 0;
display: flex;
align-items: center;
justify-content: space-between;
flex-shrink: 0;
}
.qm-popup-title {
font-family: "Tangerine", serif;
font-size: 42px;
color: #f0d9a6;
text-shadow: 0 2px 6px black;
}
.qm-popup-close {
font-size: 22px;
color: #f0d9a6;
cursor: pointer;
width: 34px;
height: 34px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 6px;
transition: 0.2s;
}
.qm-popup-close:hover {
background: rgba(255, 255, 255, 0.1);
color: #fff;
}
/* Popup Body */
.qm-popup-body {
flex: 1;
padding: 30px;
overflow-y: auto;
display: flex;
align-items: center;
justify-content: center;
font-family: "Cinzel", serif;
font-size: 18px;
color: #5c3b20;
}
/* Overlay */
#qm-overlay {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.6);
z-index: 2999;
display: none;
}
#qm-overlay.active {
display: block;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

58
public/js/quickmenu.js Normal file
View File

@ -0,0 +1,58 @@
/* ================================
Quick Menu Toggle
================================ */
const toggleBtn = document.getElementById("quickmenu-toggle");
const panel = document.getElementById("quickmenu-panel");
const overlay = document.getElementById("qm-overlay");
let menuOpen = true;
toggleBtn.addEventListener("click", () => {
menuOpen = !menuOpen;
panel.classList.toggle("hidden", !menuOpen);
toggleBtn.textContent = menuOpen ? "◀" : "▶";
});
/* ================================
Quick Menu Popups öffnen
================================ */
document.querySelectorAll(".qm-slot").forEach((slot) => {
slot.addEventListener("click", () => {
const id = slot.dataset.popup;
if (!id) return;
const popup = document.getElementById(id);
if (!popup) return;
overlay.classList.add("active");
popup.classList.add("active");
});
});
/* ================================
Quick Menu Popups schließen
================================ */
document.querySelectorAll(".qm-popup-close").forEach((btn) => {
btn.addEventListener("click", () => {
closeAllPopups();
});
});
overlay.addEventListener("click", () => {
closeAllPopups();
});
function closeAllPopups() {
document.querySelectorAll(".qm-popup").forEach((p) => {
p.classList.remove("active");
});
overlay.classList.remove("active");
}
/* Escape-Taste schließt Popup */
document.addEventListener("keydown", (e) => {
if (e.key === "Escape") closeAllPopups();
});

189
views/1v1_spielfeld.ejs Normal file
View File

@ -0,0 +1,189 @@
<!doctype html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<title><%= title || "Spielfeld" %></title>
<link
href="https://fonts.googleapis.com/css2?family=Cinzel:wght@400;700&display=swap"
rel="stylesheet"
/>
<link rel="stylesheet" href="/css/1v1.css" />
</head>
<body>
<div class="board">
<!-- TOP BAR -->
<div class="top-bar">
<div class="game-title"><%= title || "Spielfeld" %></div>
<div class="top-icons">
<div class="top-icon">⚙</div>
<div class="top-icon">🗺</div>
<div class="top-icon">📖</div>
<div class="top-icon">🏆</div>
</div>
<button class="end-turn-btn">Zug beenden</button>
</div>
<!-- LEFT AVATAR -->
<div class="avatar avatar-left" id="avLeft">
<input
type="file"
accept="image/*"
onchange="loadAvatar(this, 'avImgL', 'avLeft')"
/>
<img id="avImgL" class="av-img" />
<div class="av-placeholder" id="avPhL">
<div class="av-icon">⚔</div>
<div class="av-lbl"><%= player1 || "Spieler 1" %></div>
</div>
<div class="av-stats">
<div class="stat hp">
<span class="s-icon">❤</span>
<span class="s-val"><%= player1hp || 20 %></span>
</div>
<div class="stat mana">
<span class="s-icon">💧</span>
<span class="s-val"><%= player1mana || 3 %></span>
</div>
</div>
<div class="hp-orb"><%= player1hp || 15 %></div>
</div>
<!-- RIGHT AVATAR -->
<div class="avatar avatar-right" id="avRight">
<input
type="file"
accept="image/*"
onchange="loadAvatar(this, 'avImgR', 'avRight')"
/>
<img id="avImgR" class="av-img" />
<div class="av-placeholder" id="avPhR">
<div class="av-icon">🛡</div>
<div class="av-lbl"><%= player2 || "Spieler 2" %></div>
</div>
<div class="av-stats">
<div class="stat hp">
<span class="s-icon">❤</span>
<span class="s-val"><%= player2hp || 20 %></span>
</div>
<div class="stat mana">
<span class="s-icon">💧</span>
<span class="s-val"><%= player2mana || 3 %></span>
</div>
</div>
<div class="hp-orb"><%= player2hp || 15 %></div>
</div>
<!-- CENTER CARD ROWS -->
<div class="card-area">
<div class="row-label">Reihe 1</div>
<div class="card-row" id="row1"></div>
<div class="row-label">Reihe 2</div>
<div class="card-row" id="row2"></div>
</div>
<!-- BOTTOM BAR -->
<div class="bottom-bar">
<!-- HAND -->
<div class="hand-area" id="handArea"></div>
<!-- ACTION BUTTONS -->
<div class="action-hud">
<div class="action-row">
<div class="action-btn" title="Angriff">⚔</div>
<div class="action-btn" title="Magie">✨</div>
<div class="action-btn" title="Verteidigung">🛡</div>
</div>
<div class="action-row">
<div class="action-btn" title="Heilen">💊</div>
<div class="action-btn" title="Karte ziehen">🃏</div>
<div class="action-btn" title="Einstellungen">⚙</div>
</div>
</div>
</div>
</div>
<script>
["row1", "row2"].forEach((id) => {
const row = document.getElementById(id);
for (let i = 1; i <= 11; i++) {
const s = document.createElement("div");
s.className = "card-slot";
s.innerHTML =
'<span class="slot-icon">✦</span><span class="slot-num">' +
i +
"</span>";
row.appendChild(s);
}
});
const hand = document.getElementById("handArea");
for (let i = 0; i < 8; i++) {
const s = document.createElement("div");
s.className = "hand-slot";
s.innerHTML = '<span class="hs-icon">🃏</span>';
hand.appendChild(s);
}
function loadAvatar(input, imgId, parentId) {
const file = input.files[0];
if (!file) return;
const r = new FileReader();
r.onload = (e) => {
const img = document.getElementById(imgId);
img.src = e.target.result;
img.style.display = "block";
const parent = document.getElementById(parentId);
const ph = parent.querySelector(".av-placeholder");
if (ph) ph.style.display = "none";
};
r.readAsDataURL(file);
}
function loadPortrait(input, imgId) {
const file = input.files[0];
if (!file) return;
const r = new FileReader();
r.onload = (e) => {
const img = document.getElementById(imgId);
img.src = e.target.result;
img.style.display = "block";
img.parentElement.querySelector("span").style.display = "none";
};
r.readAsDataURL(file);
}
</script>
</body>
</html>

View File

@ -11,6 +11,7 @@
<link rel="stylesheet" href="/css/launcher.css" />
<link rel="stylesheet" href="/css/global.css" />
<link rel="stylesheet" href="/css/building.css" />
<link rel="stylesheet" href="/css/quickmenu.css" />
<style>
body {
margin: 0;
@ -209,6 +210,195 @@
</div>
<div id="map-tooltip"></div>
<!-- ================================
Quick Menu Toggle
================================ -->
<button id="quickmenu-toggle" title="Menü ein/ausblenden">◄</button>
<!-- ================================
Quick Menu Panel
================================ -->
<div id="quickmenu-panel">
<div class="qm-slot" data-popup="qm-popup-glucksbox">
<img
src="/images/quickmenu/glucksbox.png"
alt=""
onerror="this.style.display = 'none'"
/>
<span class="qm-slot-label">Glücksbox</span>
</div>
<div class="qm-slot" data-popup="qm-popup-events">
<img
src="/images/quickmenu/events.png"
alt=""
onerror="this.style.display = 'none'"
/>
<span class="qm-slot-label">Tägliche Events</span>
</div>
<div class="qm-slot" data-popup="qm-popup-heldenbonus">
<img
src="/images/quickmenu/heldenbonus.png"
alt=""
onerror="this.style.display = 'none'"
/>
<span class="qm-slot-label">Helden Bonus</span>
</div>
<div class="qm-slot" data-popup="qm-popup-sealedliga">
<img
src="/images/quickmenu/sealedliga.png"
alt=""
onerror="this.style.display = 'none'"
/>
<span class="qm-slot-label">Sealed Liga</span>
</div>
<div class="qm-slot" data-popup="qm-popup-beschwoerer">
<img
src="/images/quickmenu/beschwoerer.png"
alt=""
onerror="this.style.display = 'none'"
/>
<span class="qm-slot-label">Beschwörer der Seelen</span>
</div>
<div class="qm-slot" data-popup="qm-popup-onlinebonus">
<img
src="/images/quickmenu/onlinebonus.png"
alt=""
onerror="this.style.display = 'none'"
/>
<span class="qm-slot-label">Online Bonus</span>
</div>
<div class="qm-slot" data-popup="qm-popup-aktionen">
<img
src="/images/quickmenu/aktionen.png"
alt=""
onerror="this.style.display = 'none'"
/>
<span class="qm-slot-label">Aktionen</span>
</div>
<div class="qm-slot" data-popup="qm-popup-basar">
<img
src="/images/quickmenu/basar.png"
alt=""
onerror="this.style.display = 'none'"
/>
<span class="qm-slot-label">Basar</span>
</div>
<div class="qm-slot" data-popup="qm-popup-boosteraktion">
<img
src="/images/quickmenu/boosteraktion.png"
alt=""
onerror="this.style.display = 'none'"
/>
<span class="qm-slot-label">10 Booster Aktion</span>
</div>
<div class="qm-slot" data-popup="qm-popup-boosterjagd">
<img
src="/images/quickmenu/boosterjagd.png"
alt=""
onerror="this.style.display = 'none'"
/>
<span class="qm-slot-label">Boosterjagd</span>
</div>
</div>
<!-- ================================
Quick Menu Overlay
================================ -->
<div id="qm-overlay"></div>
<!-- ================================
Quick Menu Popups (je 1800x1000)
================================ -->
<div id="qm-popup-glucksbox" class="qm-popup">
<div class="qm-popup-header">
<span class="qm-popup-title">Glücksbox</span>
<span class="qm-popup-close">✕</span>
</div>
<div class="qm-popup-body">Inhalt folgt...</div>
</div>
<div id="qm-popup-events" class="qm-popup">
<div class="qm-popup-header">
<span class="qm-popup-title">Tägliche Events</span>
<span class="qm-popup-close">✕</span>
</div>
<div class="qm-popup-body">Inhalt folgt...</div>
</div>
<div id="qm-popup-heldenbonus" class="qm-popup">
<div class="qm-popup-header">
<span class="qm-popup-title">Helden Bonus</span>
<span class="qm-popup-close">✕</span>
</div>
<div class="qm-popup-body">Inhalt folgt...</div>
</div>
<div id="qm-popup-sealedliga" class="qm-popup">
<div class="qm-popup-header">
<span class="qm-popup-title">Sealed Liga</span>
<span class="qm-popup-close">✕</span>
</div>
<div class="qm-popup-body">Inhalt folgt...</div>
</div>
<div id="qm-popup-beschwoerer" class="qm-popup">
<div class="qm-popup-header">
<span class="qm-popup-title">Beschwörer der Seelen</span>
<span class="qm-popup-close">✕</span>
</div>
<div class="qm-popup-body">Inhalt folgt...</div>
</div>
<div id="qm-popup-onlinebonus" class="qm-popup">
<div class="qm-popup-header">
<span class="qm-popup-title">Online Bonus</span>
<span class="qm-popup-close">✕</span>
</div>
<div class="qm-popup-body">Inhalt folgt...</div>
</div>
<div id="qm-popup-aktionen" class="qm-popup">
<div class="qm-popup-header">
<span class="qm-popup-title">Aktionen</span>
<span class="qm-popup-close">✕</span>
</div>
<div class="qm-popup-body">Inhalt folgt...</div>
</div>
<div id="qm-popup-basar" class="qm-popup">
<div class="qm-popup-header">
<span class="qm-popup-title">Basar</span>
<span class="qm-popup-close">✕</span>
</div>
<div class="qm-popup-body">Inhalt folgt...</div>
</div>
<div id="qm-popup-boosteraktion" class="qm-popup">
<div class="qm-popup-header">
<span class="qm-popup-title">10 Booster Aktion</span>
<span class="qm-popup-close">✕</span>
</div>
<div class="qm-popup-body">Inhalt folgt...</div>
</div>
<div id="qm-popup-boosterjagd" class="qm-popup">
<div class="qm-popup-header">
<span class="qm-popup-title">Boosterjagd</span>
<span class="qm-popup-close">✕</span>
</div>
<div class="qm-popup-body">Inhalt folgt...</div>
</div>
<div id="game-notification-overlay"></div>
<div id="game-notification">
<div class="notification-header">
@ -228,5 +418,6 @@
window.playerName = "<%= character.name %>";
</script>
<script src="/js/chat.js"></script>
<script src="/js/quickmenu.js"></script>
</body>
</html>