piechart wip
parent
1eb8c8cbe6
commit
c0ffb4d2f1
|
|
@ -75,13 +75,12 @@
|
||||||
#roundArea[hidden]{display:none}
|
#roundArea[hidden]{display:none}
|
||||||
#options{
|
#options{
|
||||||
position:relative; width:100%; max-width:520px; aspect-ratio:1; margin:14px 0 6px;
|
position:relative; width:100%; max-width:520px; aspect-ratio:1; margin:14px 0 6px;
|
||||||
border-radius:50%; border:1px dashed var(--border);
|
border-radius:50%;
|
||||||
background: radial-gradient(240px 240px at 50% 50%, rgba(29,185,84,.08), transparent 60%);
|
|
||||||
}
|
}
|
||||||
.player-option{
|
.player-option{
|
||||||
position:absolute;
|
position:absolute;
|
||||||
left:50%; /* neu */
|
left:50%;
|
||||||
top:50%; /* neu */
|
top:50%;
|
||||||
transform-origin:center;
|
transform-origin:center;
|
||||||
background:#0f0f0f; color:var(--text);
|
background:#0f0f0f; color:var(--text);
|
||||||
border:1px solid var(--border);
|
border:1px solid var(--border);
|
||||||
|
|
@ -124,7 +123,7 @@
|
||||||
padding:10px 14px; border-radius:999px; box-shadow:var(--shadow); z-index:50; display:none}
|
padding:10px 14px; border-radius:999px; box-shadow:var(--shadow); z-index:50; display:none}
|
||||||
.toast.show{display:block}
|
.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;
|
.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;
|
border-left:1px solid var(--border); transform:translateX(100%); transition:transform .25s ease;
|
||||||
z-index:60; display:flex; flex-direction:column}
|
z-index:60; display:flex; flex-direction:column}
|
||||||
|
|
@ -137,6 +136,15 @@
|
||||||
.drawer .meta{display:flex; flex-direction:column}
|
.drawer .meta{display:flex; flex-direction:column}
|
||||||
.drawer .meta b{font-size:13px}
|
.drawer .meta b{font-size:13px}
|
||||||
.drawer .meta span{font-size:12px; color:var(--muted)}
|
.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; }
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
@ -166,17 +174,6 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-bd">
|
<div class="card-bd">
|
||||||
<!-- <div class="now" style="margin-bottom:10px">-->
|
|
||||||
<!-- <div class="cover" aria-hidden="true">-->
|
|
||||||
<!-- <svg width="48" height="48" viewBox="0 0 24 24" fill="#333"><path d="M12 3a9 9 0 1 0 .001 18.001A9 9 0 0 0 12 3Zm0 2a7 7 0 1 1-.001 14.001A7 7 0 0 1 12 5Zm0 3a4 4 0 1 0 .001 8.001A4 4 0 0 0 12 8Z"/></svg>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- <div>-->
|
|
||||||
<!-- <p id="trackTitle" class="track-title">—</p>-->
|
|
||||||
<!-- <p id="trackArtists" class="artists">—</p>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
|
|
||||||
<!-- IDs exakt wie dein game.js -->
|
|
||||||
<section id="roundArea" hidden>
|
<section id="roundArea" hidden>
|
||||||
<div id="songEmbed" style="margin-bottom:12px"></div>
|
<div id="songEmbed" style="margin-bottom:12px"></div>
|
||||||
<div id="options"></div>
|
<div id="options"></div>
|
||||||
|
|
@ -208,7 +205,7 @@
|
||||||
</aside>
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Slide-out Drawer für Songliste -->
|
<!-- Drawer -->
|
||||||
<aside class="drawer" id="songDrawer" aria-label="Zuletzt gehörte Songs">
|
<aside class="drawer" id="songDrawer" aria-label="Zuletzt gehörte Songs">
|
||||||
<header>
|
<header>
|
||||||
<h3 style="margin:0">Zuletzt gehört</h3>
|
<h3 style="margin:0">Zuletzt gehört</h3>
|
||||||
|
|
@ -217,10 +214,10 @@
|
||||||
<div class="list" id="songListArea"></div>
|
<div class="list" id="songListArea"></div>
|
||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
<!-- Toast für Clipboard-Notice -->
|
<!-- Toast -->
|
||||||
<div id="toast" class="toast" role="status" aria-live="polite"></div>
|
<div id="toast" class="toast" role="status" aria-live="polite"></div>
|
||||||
|
|
||||||
<!-- Deine existierenden Module -->
|
<!-- Module -->
|
||||||
<script type="module" src="/js/utils.js"></script>
|
<script type="module" src="/js/utils.js"></script>
|
||||||
<script type="module" src="/js/start-round.js"></script>
|
<script type="module" src="/js/start-round.js"></script>
|
||||||
<script type="module" src="/js/device-select.js"></script> <!-- füllt #deviceSelectArea -->
|
<script type="module" src="/js/device-select.js"></script> <!-- füllt #deviceSelectArea -->
|
||||||
|
|
|
||||||
|
|
@ -117,6 +117,22 @@ const optionsDiv = document.getElementById("options");
|
||||||
const resultP = document.getElementById("result");
|
const resultP = document.getElementById("result");
|
||||||
const scoreboard = document.getElementById("scoreboard");
|
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
|
// 6) Neue Runde anzeigen
|
||||||
async function handleRoundStart({ ownerOptions, songUri, trackInfos }) {
|
async function handleRoundStart({ ownerOptions, songUri, trackInfos }) {
|
||||||
// UI zurücksetzen
|
// UI zurücksetzen
|
||||||
|
|
@ -138,31 +154,45 @@ async function handleRoundStart({ ownerOptions, songUri, trackInfos }) {
|
||||||
await window.playOnSpotify(songUri, username);
|
await window.playOnSpotify(songUri, username);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Buttons kreisförmig verteilen
|
// Optionen als Tortenstücke (SVG) rendern
|
||||||
requestAnimationFrame(() => {
|
const svg = document.createElementNS(SVGNS, "svg");
|
||||||
const optsRect = optionsDiv.getBoundingClientRect();
|
svg.setAttribute("viewBox", `0 0 ${VB} ${VB}`);
|
||||||
const radius = Math.min(optsRect.width, optsRect.height) / 2 - 40; // Abstand zum Rand
|
svg.setAttribute("class", "options-svg");
|
||||||
|
optionsDiv.innerHTML = "";
|
||||||
|
optionsDiv.appendChild(svg);
|
||||||
|
|
||||||
|
const n = ownerOptions.length;
|
||||||
ownerOptions.forEach((user, i) => {
|
ownerOptions.forEach((user, i) => {
|
||||||
const btn = document.createElement("button");
|
const a0 = (360 / n) * i;
|
||||||
btn.textContent = user;
|
const a1 = (360 / n) * (i + 1);
|
||||||
btn.classList.add("player-option");
|
|
||||||
//const angle = 360 * i / ownerOptions.length;
|
|
||||||
//btn.style.transform = `rotate(${angle}deg) translateY(-${radius}px) rotate(${-angle}deg)`;
|
|
||||||
|
|
||||||
const angle = (360 / ownerOptions.length) * i;
|
const path = document.createElementNS(SVGNS, "path");
|
||||||
// zentrieren -> dann drehen -> nach außen schieben -> Text aufrecht drehen
|
path.setAttribute("d", wedgePath(CX, CY, R, a0, a1));
|
||||||
btn.style.transform = `translate(-50%, -50%) rotate(${angle}deg) translate(0, -${radius}px) rotate(${-angle}deg)`;
|
path.setAttribute("class", "wedge");
|
||||||
|
path.setAttribute("data-user", user);
|
||||||
btn.addEventListener("click", () => {
|
path.addEventListener("click", () => {
|
||||||
socket.send(JSON.stringify({
|
socket.send(JSON.stringify({
|
||||||
type: "guess",
|
type: "guess",
|
||||||
username: username,
|
username: username,
|
||||||
guess: user
|
guess: user
|
||||||
}));
|
}));
|
||||||
optionsDiv.querySelectorAll("button").forEach(b => b.disabled = true);
|
svg.querySelectorAll(".wedge").forEach(w => w.classList.add("disabled"));
|
||||||
});
|
path.classList.add("selected");
|
||||||
optionsDiv.appendChild(btn);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 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
|
// Start-Button ausblenden + Rundensektion einblenden
|
||||||
|
|
@ -210,6 +240,12 @@ function renderScoreboard(scores) {
|
||||||
|
|
||||||
function handleRoundResult({ scores, guesses, owner }) {
|
function handleRoundResult({ scores, guesses, owner }) {
|
||||||
renderScoreboard(scores);
|
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 = "";
|
resultP.innerHTML = "";
|
||||||
Object.entries(guesses).forEach(([user, guess]) => {
|
Object.entries(guesses).forEach(([user, guess]) => {
|
||||||
|
|
@ -268,5 +304,3 @@ async function playOnSpotify(trackUri, username) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
window.playOnSpotify = playOnSpotify;
|
window.playOnSpotify = playOnSpotify;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue