From c0ffb4d2f1278f0d8f165b328de3a3601d22ff80 Mon Sep 17 00:00:00 2001
From: eric <3024947@stud.hs-mannheim.de>
Date: Sun, 10 Aug 2025 21:44:56 +0200
Subject: [PATCH] piechart wip
---
src/main/resources/public/game.html | 37 ++++++-------
src/main/resources/public/js/game.js | 82 ++++++++++++++++++++--------
2 files changed, 75 insertions(+), 44 deletions(-)
diff --git a/src/main/resources/public/game.html b/src/main/resources/public/game.html
index 5bbcb54..1681340 100644
--- a/src/main/resources/public/game.html
+++ b/src/main/resources/public/game.html
@@ -75,13 +75,12 @@
#roundArea[hidden]{display:none}
#options{
position:relative; width:100%; max-width:520px; aspect-ratio:1; margin:14px 0 6px;
- border-radius:50%; border:1px dashed var(--border);
- background: radial-gradient(240px 240px at 50% 50%, rgba(29,185,84,.08), transparent 60%);
+ border-radius:50%;
}
.player-option{
position:absolute;
- left:50%; /* neu */
- top:50%; /* neu */
+ left:50%;
+ top:50%;
transform-origin:center;
background:#0f0f0f; color:var(--text);
border:1px solid var(--border);
@@ -124,7 +123,7 @@
padding:10px 14px; border-radius:999px; box-shadow:var(--shadow); z-index:50; display:none}
.toast.show{display:block}
- /* Slide-out Drawer für Songliste (wie im Beispiel) */
+ /* Slide-out Drawer */
.drawer{position:fixed; top:0; right:0; height:100%; width:340px; background:#0f0f0f;
border-left:1px solid var(--border); transform:translateX(100%); transition:transform .25s ease;
z-index:60; display:flex; flex-direction:column}
@@ -137,6 +136,15 @@
.drawer .meta{display:flex; flex-direction:column}
.drawer .meta b{font-size:13px}
.drawer .meta span{font-size:12px; color:var(--muted)}
+
+ /* === Pie-Slices === */
+ #options svg.options-svg { width:100%; height:auto; display:block; border-radius:50%; }
+ .wedge { fill:#181818; stroke:#2a2a2a; stroke-width:2; cursor:pointer; transition:filter .15s, fill .2s; }
+ .wedge:hover { filter:brightness(1.08); }
+ .wedge.selected { fill:#1db954; }
+ .wedge.correct { fill:#1db954; }
+ .wedge.disabled { pointer-events:none; opacity:.85; }
+ .wedge-label { fill:#fff; font-weight:700; font-size:14px; pointer-events:none; }
@@ -166,17 +174,6 @@
-
+
-
+
-
+
-
+
diff --git a/src/main/resources/public/js/game.js b/src/main/resources/public/js/game.js
index d5c3ee1..b5bcd12 100644
--- a/src/main/resources/public/js/game.js
+++ b/src/main/resources/public/js/game.js
@@ -117,6 +117,22 @@ const optionsDiv = document.getElementById("options");
const resultP = document.getElementById("result");
const scoreboard = document.getElementById("scoreboard");
+// --- SVG helpers für Pie-Slices ---
+const SVGNS = "http://www.w3.org/2000/svg";
+const VB = 1000; // viewBox 0..1000
+const CX = 500, CY = 500, R = 480;
+
+function polar(cx, cy, r, deg){
+ const rad = (deg - 90) * Math.PI/180; // 0° oben
+ return { x: cx + r * Math.cos(rad), y: cy + r * Math.sin(rad) };
+}
+function wedgePath(cx, cy, r, a0, a1){
+ const p0 = polar(cx, cy, r, a0);
+ const p1 = polar(cx, cy, r, a1);
+ const largeArc = ((a1 - a0 + 360) % 360) > 180 ? 1 : 0;
+ return `M ${cx} ${cy} L ${p0.x} ${p0.y} A ${r} ${r} 0 ${largeArc} 1 ${p1.x} ${p1.y} Z`;
+}
+
// 6) Neue Runde anzeigen
async function handleRoundStart({ ownerOptions, songUri, trackInfos }) {
// UI zurücksetzen
@@ -138,31 +154,45 @@ async function handleRoundStart({ ownerOptions, songUri, trackInfos }) {
await window.playOnSpotify(songUri, username);
}
- // Buttons kreisförmig verteilen
- requestAnimationFrame(() => {
- const optsRect = optionsDiv.getBoundingClientRect();
- const radius = Math.min(optsRect.width, optsRect.height) / 2 - 40; // Abstand zum Rand
- ownerOptions.forEach((user, i) => {
- const btn = document.createElement("button");
- btn.textContent = user;
- btn.classList.add("player-option");
- //const angle = 360 * i / ownerOptions.length;
- //btn.style.transform = `rotate(${angle}deg) translateY(-${radius}px) rotate(${-angle}deg)`;
+ // Optionen als Tortenstücke (SVG) rendern
+ const svg = document.createElementNS(SVGNS, "svg");
+ svg.setAttribute("viewBox", `0 0 ${VB} ${VB}`);
+ svg.setAttribute("class", "options-svg");
+ optionsDiv.innerHTML = "";
+ optionsDiv.appendChild(svg);
- const angle = (360 / ownerOptions.length) * i;
- // zentrieren -> dann drehen -> nach außen schieben -> Text aufrecht drehen
- btn.style.transform = `translate(-50%, -50%) rotate(${angle}deg) translate(0, -${radius}px) rotate(${-angle}deg)`;
+ const n = ownerOptions.length;
+ ownerOptions.forEach((user, i) => {
+ const a0 = (360 / n) * i;
+ const a1 = (360 / n) * (i + 1);
- btn.addEventListener("click", () => {
- socket.send(JSON.stringify({
- type: "guess",
- username: username,
- guess: user
- }));
- optionsDiv.querySelectorAll("button").forEach(b => b.disabled = true);
- });
- optionsDiv.appendChild(btn);
+ const path = document.createElementNS(SVGNS, "path");
+ path.setAttribute("d", wedgePath(CX, CY, R, a0, a1));
+ path.setAttribute("class", "wedge");
+ path.setAttribute("data-user", user);
+ path.addEventListener("click", () => {
+ socket.send(JSON.stringify({
+ type: "guess",
+ username: username,
+ guess: user
+ }));
+ svg.querySelectorAll(".wedge").forEach(w => w.classList.add("disabled"));
+ path.classList.add("selected");
});
+
+ // Label mittig im Segment
+ const mid = (a0 + a1) / 2;
+ const P = polar(CX, CY, R * 0.58, mid);
+ const text = document.createElementNS(SVGNS, "text");
+ text.setAttribute("x", P.x);
+ text.setAttribute("y", P.y);
+ text.setAttribute("class", "wedge-label");
+ text.setAttribute("text-anchor", "middle");
+ text.setAttribute("dominant-baseline", "middle");
+ text.textContent = user;
+
+ svg.appendChild(path);
+ svg.appendChild(text);
});
// Start-Button ausblenden + Rundensektion einblenden
@@ -210,6 +240,12 @@ function renderScoreboard(scores) {
function handleRoundResult({ scores, guesses, owner }) {
renderScoreboard(scores);
+ // korrektes Segment hervorheben
+ try {
+ document.querySelectorAll("#options .wedge").forEach(w => {
+ if (w.getAttribute("data-user") === owner) w.classList.add("correct");
+ });
+ } catch(e) {}
resultP.innerHTML = "";
Object.entries(guesses).forEach(([user, guess]) => {
@@ -268,5 +304,3 @@ async function playOnSpotify(trackUri, username) {
}
}
window.playOnSpotify = playOnSpotify;
-
-