Initial VTuber Awards implementation
This commit is contained in:
Vendored
+157
@@ -0,0 +1,157 @@
|
||||
const categories = [
|
||||
{
|
||||
icon: "✦",
|
||||
color: "linear-gradient(160deg, #c49aef, #8b6ce7)",
|
||||
title: "VTuber des Jahres",
|
||||
text: "Die herausragendste VTuberin des Jahres 2025.",
|
||||
},
|
||||
{
|
||||
icon: "🎙",
|
||||
color: "linear-gradient(160deg, #d7e7ff, #8ea9ef)",
|
||||
title: "Bestes Live Event",
|
||||
text: "Das beste Live Event, das die Community begeistert hat.",
|
||||
},
|
||||
{
|
||||
icon: "🎬",
|
||||
color: "linear-gradient(160deg, #f7dfb2, #dba84b)",
|
||||
title: "Bester Content Creator",
|
||||
text: "Kreativitaet, Konsistenz und Impact in einem.",
|
||||
},
|
||||
{
|
||||
icon: "🌿",
|
||||
color: "linear-gradient(160deg, #e9f3bb, #a7c95d)",
|
||||
title: "Bester New VTuber",
|
||||
text: "Rising Stars, die dieses Jahr durchgestartet sind.",
|
||||
},
|
||||
{
|
||||
icon: "🤍",
|
||||
color: "linear-gradient(160deg, #ffd4e4, #f28ab1)",
|
||||
title: "Beste Community",
|
||||
text: "Die herzlichste und aktivste Community des Jahres.",
|
||||
},
|
||||
];
|
||||
|
||||
const winners = {
|
||||
2025: [
|
||||
["Hoshimi Miyu", "VTuber des Jahres", "Conveyed"],
|
||||
["Eclipse Euphoria", "Bestes Live Event", "Conveyed"],
|
||||
["Kurainu", "Bester Content Creator", "Conveyed"],
|
||||
["Lumi Airi", "Bester New VTuber", "Conveyed"],
|
||||
["Pyonkichi Kingdom", "Beste Community", "Conveyed"],
|
||||
],
|
||||
2024: [
|
||||
["Miyu Astra", "VTuber des Jahres", "Winner"],
|
||||
["Nova Hall", "Bestes Live Event", "Winner"],
|
||||
["Shiro Ch.", "Bester Content Creator", "Winner"],
|
||||
["Airi Bloom", "Bester New VTuber", "Winner"],
|
||||
["Moonrelay", "Beste Community", "Winner"],
|
||||
],
|
||||
2023: [
|
||||
["Tenshi Vox", "VTuber des Jahres", "Winner"],
|
||||
["Umi Nights", "Bestes Live Event", "Winner"],
|
||||
["Rin Atelier", "Bester Content Creator", "Winner"],
|
||||
["Starbyte", "Bester New VTuber", "Winner"],
|
||||
["Luna Port", "Beste Community", "Winner"],
|
||||
],
|
||||
2022: [
|
||||
["Aoi Sakura", "VTuber des Jahres", "Winner"],
|
||||
["Kitsu Stage", "Bestes Live Event", "Winner"],
|
||||
["Kohaku Live", "Bester Content Creator", "Winner"],
|
||||
["Mira Veil", "Bester New VTuber", "Winner"],
|
||||
["Neko Choir", "Beste Community", "Winner"],
|
||||
],
|
||||
};
|
||||
|
||||
const faqs = [
|
||||
["Wer kann nominieren und voten?", "Jede Person mit Twitch Login. Das Konto wird bei der ersten Anmeldung im Hintergrund angelegt."],
|
||||
["Wie oft kann ich abstimmen?", "Pro Kategorie eine Stimme. Bis zur Deadline kannst du deine Auswahl erneut bearbeiten und absenden."],
|
||||
["Wie werden Gewinner bestimmt?", "Aktuell rein community-basiert. Eine spaetere Mischung mit Jury oder Panel bleibt offen."],
|
||||
["Was ist mit Bots und Betrug?", "Missbrauchsschutz laeuft moeglichst unsichtbar: Twitch Login, Rate Limits und interne Risiko-Flags."],
|
||||
["Kann das Team Kategorien aendern?", "Ja. Kategorien und Unterkategorien werden pro Jahr durch das Team gepflegt und freigeschaltet."],
|
||||
];
|
||||
|
||||
function renderCategories() {
|
||||
const root = document.getElementById("category-grid");
|
||||
root.innerHTML = categories
|
||||
.map(
|
||||
(item) => `
|
||||
<article class="category-card">
|
||||
<div class="category-orb" style="background:${item.color}">${item.icon}</div>
|
||||
<h3>${item.title}</h3>
|
||||
<p>${item.text}</p>
|
||||
</article>
|
||||
`,
|
||||
)
|
||||
.join("");
|
||||
}
|
||||
|
||||
function renderWinners(year = "2025") {
|
||||
const root = document.getElementById("winner-grid");
|
||||
const yearLabel = document.getElementById("archive-year-label");
|
||||
yearLabel.textContent = year;
|
||||
|
||||
root.innerHTML = winners[year]
|
||||
.map(
|
||||
([name, category, tag], index) => `
|
||||
<article class="winner-card">
|
||||
<div class="winner-thumb" data-tag="${tag}" style="background:${winnerGradient(index)}"></div>
|
||||
<div class="winner-info">
|
||||
<strong>${name}</strong>
|
||||
<small>${category}</small>
|
||||
</div>
|
||||
</article>
|
||||
`,
|
||||
)
|
||||
.join("");
|
||||
}
|
||||
|
||||
function winnerGradient(index) {
|
||||
const gradients = [
|
||||
"linear-gradient(160deg, rgba(208,189,255,.78), rgba(255,231,198,.72))",
|
||||
"linear-gradient(160deg, rgba(151,128,212,.84), rgba(248,222,180,.52))",
|
||||
"linear-gradient(160deg, rgba(201,192,255,.82), rgba(250,215,168,.6))",
|
||||
"linear-gradient(160deg, rgba(196,221,255,.82), rgba(250,235,195,.68))",
|
||||
"linear-gradient(160deg, rgba(255,213,225,.82), rgba(249,225,176,.62))",
|
||||
];
|
||||
return gradients[index % gradients.length];
|
||||
}
|
||||
|
||||
function bindYears() {
|
||||
document.querySelectorAll(".year-pill").forEach((button) => {
|
||||
button.addEventListener("click", () => {
|
||||
document.querySelectorAll(".year-pill").forEach((pill) => pill.classList.remove("is-active"));
|
||||
button.classList.add("is-active");
|
||||
renderWinners(button.dataset.year);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function renderFaq() {
|
||||
const root = document.getElementById("faq-list");
|
||||
root.innerHTML = faqs
|
||||
.map(
|
||||
([question, answer], index) => `
|
||||
<div class="faq-item ${index === 0 ? "is-open" : ""}">
|
||||
<button class="faq-button" type="button">
|
||||
<span>${question}</span>
|
||||
<strong>+</strong>
|
||||
</button>
|
||||
<div class="faq-panel-copy">
|
||||
<p>${answer}</p>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
)
|
||||
.join("");
|
||||
|
||||
root.querySelectorAll(".faq-item").forEach((item) => {
|
||||
item.querySelector(".faq-button").addEventListener("click", () => {
|
||||
item.classList.toggle("is-open");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
renderCategories();
|
||||
renderWinners();
|
||||
bindYears();
|
||||
renderFaq();
|
||||
Reference in New Issue
Block a user