Compare commits

10 Commits

Author SHA1 Message Date
1a09ea3d80 -decimals
- round decimals on leaderboard
2025-11-09 02:26:57 -05:00
ff7c48dab4 -leaderboard scores
- will not work over 1000 points
2025-11-06 03:42:41 -05:00
6c2b897522 -red progress bar 2025-11-05 23:18:56 -05:00
192f3c0eb1 - cleanup 2025-11-04 12:19:37 -05:00
8e95f378d7 - OBS progress bar bugfix 2025-11-04 12:18:33 -05:00
f2fc02ff7e v5-Progress Bar, Finale
- added progress bar and 00:00 timer color change (first included in hot garbage)

- cleanup of local testing code

- adjustments to finale/stop logic to ensure final update when the clock stops

- minor polish

- ready for production!!! (I hope)
2025-11-03 15:57:11 -05:00
75cdfcf09a Add timer end checking 2025-11-03 22:20:10 +10:00
11ca4470fe -hot garbage
- never send this version live
2025-11-03 06:58:14 -05:00
2d9e320d42 v4.1-Spacing adjustments
- relaxed vertical spacing and increased horizontal gap between text and graphic

- cleanup
2025-11-02 04:45:52 -05:00
da6ae0b9c3 v4-Animation rework
- added JS logic for controlling animations based on text length

- added duplicate elements for looping scroll effect and JS logic for populating them
2025-11-02 03:45:11 -05:00
8 changed files with 362 additions and 692 deletions

View File

@@ -8,58 +8,84 @@
<link href='https://fonts.googleapis.com/css?family=Inter' rel='stylesheet'> <link href='https://fonts.googleapis.com/css?family=Inter' rel='stylesheet'>
<link rel="stylesheet" href="timer.css" /> <link rel="stylesheet" href="timer.css" />
<script src="timer.js"></script> <script src="timer.js"></script>
<title>v2 onefont</title> <title>Lilac Timer</title>
</head> </head>
<body> <body>
<main> <main>
<div class='contentContainer'> <div class='contentContainer'>
<img class='mainHeart' src='src/youve_got_mail_whiteheart.png'>
<img class='mainHeart' src='src/youvegotmail.webp'>
<div class='infoWrap'> <div class='infoWrap'>
<div class='infoGroup'> <div class='infoGroup'>
<div class='infoBox' id='InfoBox3'> <div class='infoBox' id='InfoBox3'>
<p id='TopUsers'> <p id='TopUsers'>
Leaderboard: Leaderboard:
</p> </p>
<div class='giftUserWrap'>
<div class='giftUserRow' id='GiftUserRow1'> <div class='rightFadeWrap' id='RightFadeWrapInfoBox3'>
<p class='giftUserNum' id='GiftUserNum1'> <div class='giftUserWrap' id='GiftUserWrap'>
1 <div class='giftUserRow' id='GiftUserRow1'>
</p> <p class='giftUserNum' id='GiftUserNum1'>
<div class='scrollWrap' id='ScrollWrapName1'> 1
<div class='scrollWrapW' id='ScrollWrapNameW1'> </p>
<p class='giftUserName'id='GiftUserName1'> <div class='scrollWrap' id='ScrollWrapName1'>
Usernamethatisverylong <div class='scrollWrapW' id='ScrollWrapNameW1'>
</p> <p class='giftUserName'id='GiftUserName1'>
Usernamethatisverylong
</p>
<p class='giftUserNameDupe'id='GiftUserNameDupe1'>
Usernamethatisverylong
</p>
</div>
</div> </div>
<p class='giftUserScore' id='GiftUserScore1'>
0000
</p>
</div> </div>
</div> <div class='giftUserRow' id='GiftUserRow2'>
<div class='giftUserRow' id='GiftUserRow2'> <p class='giftUserNum' id='GiftUserNum2'>
<p class='giftUserNum' id='GiftUserNum2'> 2
2 </p>
</p> <div class='scrollWrap' id='ScrollWrapName2'>
<div class='scrollWrap' id='ScrollWrapName2'> <div class='scrollWrapW' id='ScrollWrapNameW2'>
<div class='scrollWrapW' id='ScrollWrapNameW2'> <p class='giftUserName'id='GiftUserName2'>
<p class='giftUserName'id='GiftUserName2'> Usernamethatisverylong
Usernamethatisverylong </p>
</p> <p class='giftUserNameDupe'id='GiftUserNameDupe2'>
Usernamethatisverylong
</p>
</div>
</div> </div>
<p class='giftUserScore' id='GiftUserScore2'>
25
</p>
</div> </div>
</div> <div class='giftUserRow' id='GiftUserRow3'>
<div class='giftUserRow' id='GiftUserRow3'> <p class='giftUserNum' id='GiftUserNum3'>
<p class='giftUserNum' id='GiftUserNum3'> 3
3 </p>
</p> <div class='scrollWrap' id='ScrollWrapName3'>
<div class='scrollWrap' id='ScrollWrapName3'> <div class='scrollWrapW' id='ScrollWrapNameW3'>
<div class='scrollWrapW' id='ScrollWrapNameW3'> <p class='giftUserName'id='GiftUserName3'>
<p class='giftUserName'id='GiftUserName3'> Usernamethatisverylong
Usernamethatisverylong </p>
</p> <p class='giftUserNameDupe'id='GiftUserNameDupe3'>
Usernamethatisverylong
</p>
</div>
</div> </div>
<p class='giftUserScore' id='GiftUserScore3'>
1
</p>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<img class='mainHeart' id='SecondHeart' src='src/youve_got_mail_whiteheart.png'>
<img class='mainHeart' id='SecondHeart' src='src/youvegotmail.webp'>
<div class='infoBox' id='InfoBox1'> <div class='infoBox' id='InfoBox1'>
<h1 id='Timer'> <h1 id='Timer'>
00:00 00:00
@@ -68,23 +94,37 @@
!subathon for details !subathon for details
</p> </p>
</div> </div>
<div class='infoBox' id='InfoBox2'> <div class='infoBox' id='InfoBox2'>
<p id='GoalLabel'> <p id='GoalLabel'>
Next Goal: Next Goal:
</p> </p>
<div class='scrollWrap' id='ScrollWrapGoal'> <div class='rightFadeWrap' id='RightFadeWrapInfoBox2'>
<div class='scrollWrapW' id='ScrollWrapGoalW'> <div class='scrollWrap' id='ScrollWrapGoal'>
<p id='GoalName'> <div class='scrollWrapW' id='ScrollWrapGoalW'>
Discord Watch Party + Puzzles <p id='GoalName'>
</p> Discord Watch Party + Puzzles
</p>
<p id='GoalNameDupe'>
Discord Watch Party + Puzzles
</p>
</div>
</div> </div>
</div> </div>
<div id='GoalProgressWrap'> <div id='GoalProgressWrap'>
<div id='GoalProgressBar'>
<p id='GoalProgressTransparent' style='color: transparent;'>
1234/5678
</p>
</div>
<p id='GoalProgress'> <p id='GoalProgress'>
1234/5678 1234/5678
</p> </p>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -1,222 +0,0 @@
:root {
--time-color: #453960;
--details-color: #403060;
--background-color: transparent;
}
* {
box-sizing: border-box;
}
html, body {
height: 100%;
margin: 0;
padding: 0;
font-family: 'Inter', sans-serif;
background-color: var(--background-color);
overflow: hidden;
}
main {
font-family: "Silkscreen", sans-serif;
font-weight: 400;
font-style: normal;
color: #EA4045;
height: 100%;
}
h1 {
margin: 0;
font-size: 3.4em;
color: #404145;
font-weight: normal;
}
h2 {
margin: 0;
font-size: 1.4em;
color: #404145;
font-weight: normal;
}
h3 {
margin: 0;
font-size: 1em;
color: #404145;
font-weight: normal;
}
p {
margin: 0;
font-size: 1em;
}
.contentContainer {
height: fit-content;
width: fit-content;
position: relative;
text-align: center;
}
#MainHeart {
max-height: 100vh;
max-width: 100vw;
}
.infoWrap {
container-type: size;
height: 100%;
width: 100%;
position: absolute;
left: 0px;
top: 0px;
display: grid;
grid-template-columns: 56% 34% 1fr;
/*
grid-template-rows: 11% 28% 16% 16% 1fr;
*/
grid-template-rows: 11% 1fr 29%;
place-items: center;
text-wrap: nowrap;
}
.infoGroup {
display: block;
height: 100%;
width: 100%;
grid-column-start: 2;
grid-column-end: 2;
grid-row-start: 2;
grid-row-end: 2;
}
.infoBox {
height: auto;
width: 100%;
/*
display: grid;
grid-template-columns: repeat(1, 1fr);
grid-auto-rows: auto;
place-items: center;
*/
font-size: 4cqh;
}
#InfoBox1 {
margin-top: 4cqh;
/*
justify-self: left;
align-self: stretch;
*/
/*
transform: translate(-8%, 5%);
*/
}
#InfoBox2 {
/*
display: grid;
width: 100%;
justify-self: left;
align-self: stretch;
*/
transform: translate(0%, -12%);
}
#InfoBox3 {
grid-template-columns: 1fr;
grid-template-rows: 1fr 23% 23% 23%;
transform: translate(0%, -16%) scale(1, 1);
/*
justify-self: left;
align-self: stretch;
transform: translate(0%, -32%);
*/
}
#Timer {
transform: translate(-9%, 3%) scale(.95, 1.2);
}
#TimerInfo {
transform: translate(0%, -60%);
font-size: 1em;
display: none;
}
#GoalLabel {
transform: translate(5%, 0%) scale(1.05, 1.2);
}
#GoalName {
width: 100%;
transform: translate(8%, -10%) scale(1, 1.4);
color: #32B993;
text-wrap: nowrap;
overflow: hidden;
mask-image: linear-gradient(to right, black 85%, transparent 100%);
}
#GoalProgressWrap {
width: fit-content;
padding-left: .8cqh;
padding-right: .8cqh;
transform: translate(7%, 0%) scale(1, 1);
border-radius: 3cqh;
border: .4cqh solid;
border-color: #404145;
margin: 0 auto 0 auto;
}
#GoalProgress {
transform: translate(0%, -8%) scale(1, 1.4);
font-size: 1.3em;
text-align: center;
/*
font-weight: bold;
*/
}
#TopUsers {
transform: translate(6%, 0%) scale(1.15, 1.2);
font-weight: normal;
font-size: 1.1em;
}
.giftUserWrap {
transform: translate(18%, -8%) scale(1, 1);
}
.giftUserRow {
width: 100%;
display: grid;
grid-template-columns: 8% 1fr;
grid-template-rows: 1fr;
text-wrap: nowrap;
overflow: hidden;
text-align: left;
justify-self: left;
text-align: center;
transform: translate(0%, 0%) scale(1, 1.2);
font-size: 1.4em;
line-height: 90%;
}
.giftUserName {
margin-left: 0%;
color: #32B993;
text-align: left;
}
#GiftUserName1 {
width: 24cqw;
mask-image: linear-gradient(to right, black 85%, transparent 100%);
}
#GiftUserName2 {
width: 20cqw;
mask-image: linear-gradient(to right, black 75%, transparent 100%);
}
#GiftUserName3 {
width: 14cqw;
mask-image: linear-gradient(to right, black 60%, transparent 100%);
}

View File

@@ -1,76 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Silkscreen:wght@400;700&family=VT323&display=swap" rel="stylesheet">
<link href='https://fonts.googleapis.com/css?family=Inter' rel='stylesheet'>
<link rel="stylesheet" href="no-bold.css" />
<script src="timer.js"></script>
<title>v2 onefont</title>
</head>
<body>
<main>
<div class='contentContainer'>
<img id='MainHeart' src='src/youve_got_mail_whiteheart.png'>
<div class='infoWrap'>
<div class='infoGroup'>
<div class='infoBox' id='InfoBox1'>
<h1 id='Timer'>
00:00
</h1>
<p id='TimerInfo'>
!subathon for details
</p>
</div>
<div class='infoBox' id='InfoBox2'>
<h2 id='GoalLabel'>
Next Goal:
</h2>
<h3 id='GoalName'>
Discord Watch Party + Puzzles
</h3>
<div id='GoalProgressWrap'>
<p id='GoalProgress'>
1234/5678
</p>
</div>
</div>
<div class='infoBox' id='InfoBox3'>
<h2 id='TopUsers'>
Leaderboard:
</h2>
<div class='giftUserWrap'>
<div class='giftUserRow' id='GiftUserRow1'>
<p class='giftUserNum' id='GiftUserNum1'>
1
</p>
<p class='giftUserName'id='GiftUserName1'>
Usernamethatisverylong
</p>
</div>
<div class='giftUserRow' id='GiftUserRow2'>
<p class='giftUserNum' id='GiftUserNum2'>
2
</p>
<p class='giftUserName'id='GiftUserName2'>
Usernamethatisverylong
</p>
</div>
<div class='giftUserRow' id='GiftUserRow3'>
<p class='giftUserNum' id='GiftUserNum3'>
3
</p>
<p class='giftUserName'id='GiftUserName3'>
Usernamethatisverylong
</p>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
</body>
</html>

BIN
src/youvegotmail.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

162
timer.css
View File

@@ -28,7 +28,7 @@ main {
h1 { h1 {
margin: 0; margin: 0;
font-size: 3.4em; font-size: 3.6em;
color: #404145; color: #404145;
font-weight: normal; font-weight: normal;
} }
@@ -49,8 +49,7 @@ h3 {
p { p {
margin: 0; margin: 0;
font-size: 1.4em; font-size: 1.3em;
line-height: 95%;
} }
.contentContainer { .contentContainer {
@@ -62,7 +61,7 @@ p {
.mainHeart { .mainHeart {
max-height: 100vh; max-height: 100vh;
max-width: 75vw; max-width: 72vw;
} }
#SecondHeart { #SecondHeart {
@@ -98,31 +97,37 @@ p {
height: auto; height: auto;
width: 100%; width: 100%;
font-size: 4cqh; font-size: 4cqh;
transform: translate(12%, -68%);
} }
#InfoBox1 { #InfoBox1 {
transform: translate(-2%, 0%);
margin-top: -50%;
} }
#InfoBox2 { #InfoBox2 {
transform: translate(-1%, -88%); /* -- !!DO NOT REMOVE!! --
Removing this transform kills the goal label and I do not know why
*/
transform: translate(0%, 0%);
} }
#InfoBox3 { #InfoBox3 {
width: 110%; width: 142%;
position: relative; position: relative;
transform: translate(88%, 25%) scale(1, 1); transform: translate(65%, 10%) scale(1, 1);
border-radius: 3cqh; border-radius: 3cqh;
border: .4cqh solid; border: .4cqh solid;
border-color: #00A0F3; border-color: #00A0F3;
background-color: white; background-color: white;
padding: .4ch 0 .4ch 0;
} }
#Timer { #Timer {
/*
margin-top: 10%; margin-top: 10%;
margin-bottom: 2%; margin-bottom: 2%;
transform: translate(-7.5%, 3%) scale(.95, 1.2); */
transform: translate(0%, 0%) scale(.95, 1.2);
} }
#TimerInfo { #TimerInfo {
@@ -131,7 +136,6 @@ p {
} }
#GoalLabel { #GoalLabel {
transform: translate(5%, 0%) scale(1);
color: #404145; color: #404145;
} }
@@ -140,45 +144,86 @@ p {
position: relative; position: relative;
color: #32B993; color: #32B993;
text-wrap: nowrap; text-wrap: nowrap;
animation: myScroll 12s linear infinite; display: inline-block;
padding-right: 4%;
transform: translate(.5ch, 0%);
/* --- animation-duration = JS VAR --- */
}
#GoalNameDupe {
width: fit-content;
position: relative;
color: #32B993;
text-wrap: nowrap;
padding-right: 4%;
transform: translate(.5ch, 0%);
/* --- animation-duration = JS VAR --- */
} }
#GoalProgressWrap { #GoalProgressWrap {
width: fit-content; width: fit-content;
padding-left: .8cqh; padding-left: .8cqh;
padding-right: .8cqh; padding-right: .8cqh;
transform: translate(7%, 0%) scale(1, 1);
border-radius: 3cqh; border-radius: 3cqh;
border: .4cqh solid; border: .4cqh solid;
border-color: #404145; border-color: #404145;
margin: 0 auto .8cqh auto; margin: .4ch auto 0 auto;
overflow: hidden;
}
#GoalProgressBar {
width: 110%;
background-color: #FC98B3;
transform: translate(-5%, 0%) scale(1, 1.5);
} }
#GoalProgress { #GoalProgress {
transform: translate(0%, -8%) scale(1); transform: translate(0%, -8%) scale(1);
text-align: center; text-align: center;
margin-top: -19%;
color: #404145;
} }
#TopUsers { #TopUsers {
margin-bottom: 2%; margin-bottom: 2%;
transform: translate(0%, 0%) scale(1);
font-weight: normal; font-weight: normal;
color: #404145; color: #404145;
} }
.giftUserWrap { .giftUserWrap {
transform: translate(11%, -8%) scale(1, 1); transform: translate(9%, -8%) scale(1, 1);
} }
.giftUserRow { .giftUserRow {
width: 100%; width: 100%;
display: grid; display: grid;
grid-template-columns: 8% 1fr; grid-template-columns: 2ch 14ch 5ch;
grid-template-rows: 1fr; grid-template-rows: 1fr;
text-wrap: nowrap; text-wrap: nowrap;
overflow: hidden; overflow: hidden;
text-align: center; text-align: center;
transform: translate(0%, 0%) scale(1, 1); }
.giftUserNum {
border-right: 1.5px solid #00A0F3;
border-image: linear-gradient(to top,
transparent 0%,
transparent 5%,
#00A0F3 35%,
#00A0F3 65%,
transparent 95%) 1;
}
.giftUserScore {
border-left: 1.5px solid #00A0F3;
border-image: linear-gradient(to top,
transparent 0%,
transparent 5%,
#00A0F3 40%,
#00A0F3 60%,
transparent 95%) 1;
text-align: right;
padding-right: .25ch;
} }
.giftUserName { .giftUserName {
@@ -187,25 +232,80 @@ p {
position: relative; position: relative;
color: #32B993; color: #32B993;
text-align: left; text-align: left;
display: inline-block;
padding-right: 4%;
transform: translate(.5ch, 0%);
}
.giftUserNameDupe {
width: fit-content;
margin-left: 0%;
position: relative;
color: #32B993;
text-align: left;
padding-right: 4%;
transform: translate(.5ch, 0%);
} }
#GiftUserName1 { #GiftUserName1 {
animation: myScroll 9s linear infinite; /* --- animation-duration = JS VAR --- */
} }
#GiftUserName2 { #GiftUserName2 {
animation: myScroll 9s 3s linear infinite; /* --- animation-duration = JS VAR --- */
} }
#GiftUserName3 { #GiftUserName3 {
animation: myScroll 9s 6s linear infinite; /* --- animation-duration = JS VAR --- */
}
#GiftUserNameDupe1 {
/* --- animation-duration = JS VAR --- */
}
#GiftUserNameDupe2 {
/* --- animation-duration = JS VAR --- */
}
#GiftUserNameDupe3 {
/* --- animation-duration = JS VAR --- */
} }
.scrollWrap { .scrollWrap {
width: 100%; width: 100%;
mask-image: linear-gradient(to right, transparent 0%, black 5%, black 85%, transparent 100%); }
.rightFadeWrap {
/*
mask-image: linear-gradient(to right, black 75%, transparent 90%);
*/
}
#RightFadeWrapInfoBox2 {
width: 90%;
border-left: 1.5px solid #00A0F3;
border-right: 1.5px solid #00A0F3;
border-image: linear-gradient(to top,
transparent 0%,
transparent 5%,
#00A0F3 40%,
#00A0F3 60%,
transparent 95%) 1;
transform: translate(1ch, 0%) scale(1);
}
.fadeLeft {
mask-image: linear-gradient(to right,
transparent 0%,
black 1ch,
black calc(100% - 2ch),
transparent 100%);
} }
#ScrollWrapGoal { #ScrollWrapGoal {
transform: translate(8%, -10%) scale(1); /*
width: 90%;
*/
} }
.scrollWrapName { .scrollWrapName {
@@ -213,16 +313,22 @@ p {
.scrollWrapW { .scrollWrapW {
width: fit-content; width: fit-content;
display: flex;
} }
#ScrollWrapGoalW { #ScrollWrapGoalW {
} }
.hide {
display: none;
}
.scrollAnim {
animation: myScroll linear infinite;
}
@keyframes myScroll { @keyframes myScroll {
0% {left: 0%; top: 0%;} 0% {left: 0%; top: 0%;}
10% {left: 0%; top: 0%;} 42% {left: 0%; top: 0%;}
85% {left: -100%; top: 0%;} 100% {left: -54%; top: 0%;}
89.99% {left: -100%; top: 0%;}
90% {left: 0%; top: 100%;}
100% {left: 0%; top: 0%;}
} }

161
timer.js
View File

@@ -8,6 +8,7 @@ class Timer {
constructor(renderer, timer_data) { constructor(renderer, timer_data) {
this.renderer = renderer; this.renderer = renderer;
this.destroying = false; this.destroying = false;
this.ended = false;
this.update_from_data(timer_data); this.update_from_data(timer_data);
} }
@@ -32,13 +33,34 @@ class Timer {
this.leaderboard = timer_data.leaderboard; this.leaderboard = timer_data.leaderboard;
} }
check_ended() {
if (!this.ended && this.end_at < new Date()) {
this.ended = true;
this.renderer.finale();
}
return this.ended;
}
set_ended() {
if (!this.ended && this.end_at < new Date()) {
this.ended = true;
this.renderer.finale();
}
}
render_time() { render_time() {
if (this.check_ended()) {
return;
}
this.renderer.render_time( this.renderer.render_time(
Math.floor((this.end_at - new Date()) / 1000) Math.floor((this.end_at - new Date()) / 1000)
); );
} }
render() { render() {
if (this.ended) {
return;
}
// Render goal // Render goal
if (this.next_goal != null) { if (this.next_goal != null) {
this.renderer.render_current_goal( this.renderer.render_current_goal(
@@ -46,21 +68,26 @@ class Timer {
this.total_contribution, this.total_contribution,
this.next_goal.required, this.next_goal.required,
); );
this.renderer.animate();
} else if (this.last_goal != null) { } else if (this.last_goal != null) {
this.renderer.render_current_goal( this.renderer.render_current_goal(
this.last_goal.name, this.last_goal.name,
this.total_contribution, this.total_contribution,
this.last_goal.required, this.last_goal.required,
); );
this.renderer.animate();
} else { } else {
this.renderer.clear_current_goal(); this.renderer.clear_current_goal();
} }
// Render leaderboard // Render leaderboard
this.renderer.render_users(this.leaderboard); this.renderer.render_users(this.leaderboard);
this.renderer.animate();
// Render timer // Render timer
this.render_time(); this.render_time();
this.set_ended();
} }
/** /**
@@ -74,7 +101,6 @@ class Timer {
setTimeout(this.tick.bind(this), 1000); setTimeout(this.tick.bind(this), 1000);
} }
} }
} }
} }
@@ -88,41 +114,127 @@ class TimerRenderer {
// Name of the goal to display // Name of the goal to display
this.goal_name = document.getElementById("GoalName") this.goal_name = document.getElementById("GoalName")
this.goal_namedupe = document.getElementById("GoalNameDupe")
// 1524/3000 Points // 1524/3000 Points
this.goal_progress = document.getElementById("GoalProgress") this.goal_progress = document.getElementById("GoalProgress")
this.goal_bar = document.getElementById("GoalProgressBar")
// Top 3 Gifters // Top 3 Gifters
this.topusers_label = document.getElementById("TopUsers") this.topusers_label = document.getElementById("TopUsers")
// Leaderboard items // Leaderboard items
// 1. (or points?) // 1. (or points?) (1 as in 1st place, static)
this.topusers_user1_num = document.getElementById("GiftUserNum1") this.topusers_user1_num = document.getElementById("GiftUserNum1")
// Name of user 1 // Name of user 1
this.topusers_user1_name = document.getElementById("GiftUserName1") this.topusers_user1_name = document.getElementById("GiftUserName1")
this.topusers_userdupe1_name = document.getElementById("GiftUserNameDupe1")
this.topusers_user1_score = document.getElementById("GiftUserScore1")
this.topusers_user2_num = document.getElementById("GiftUserNum2") this.topusers_user2_num = document.getElementById("GiftUserNum2")
this.topusers_user2_name = document.getElementById("GiftUserName2") this.topusers_user2_name = document.getElementById("GiftUserName2")
this.topusers_userdupe2_name = document.getElementById("GiftUserNameDupe2")
this.topusers_user2_score = document.getElementById("GiftUserScore2")
this.topusers_user3_num = document.getElementById("GiftUserNum3") this.topusers_user3_num = document.getElementById("GiftUserNum3")
this.topusers_user3_name = document.getElementById("GiftUserName3") this.topusers_user3_name = document.getElementById("GiftUserName3")
this.topusers_userdupe3_name = document.getElementById("GiftUserNameDupe3")
this.topusers_user3_score = document.getElementById("GiftUserScore3")
// -- Animation --
// Left-fade wrappers
this.scrollwraps = document.getElementsByClassName("scrollWrap")
// Parent wrappers
this.scrollboxes = [document.getElementById("GiftUserRow1"),
document.getElementById("GiftUserRow2"),
document.getElementById("GiftUserRow3"),
document.getElementById("ScrollWrapGoal")]
// Leaderboard names
this.userboxes = [this.topusers_user1_name, this.topusers_user2_name, this.topusers_user3_name]
this.userdupeboxes = [this.topusers_userdupe1_name, this.topusers_userdupe2_name, this.topusers_userdupe3_name]
// Thank you!
this.thankyou = "Thank you! The subathon has now ended, thank you so much for contributions and viewership to celebrate!"
}
// -- Toggles animation if text overflows container and adjusts speed for uniform movement --
animate() {
for (let i = 0; i < this.scrollboxes.length; i++) {
// Check whether the itteration is a username or goal
if (this.scrollboxes[i].id == 'ScrollWrapGoal') {
// Check if element text overflows
if (this.goal_name.getBoundingClientRect().width > (this.scrollboxes[i].getBoundingClientRect().width)) {
// Toggle animation
this.goal_name.classList.add("scrollAnim");
this.goal_namedupe.classList.add("scrollAnim");
this.goal_namedupe.style.display = 'inline-block';
this.scrollwraps[i].classList.add("fadeLeft");
// Set animation speed
this.goal_name.style.animationDuration = `${this.goal_name.getBoundingClientRect().width / 40}s`;
this.goal_namedupe.style.animationDuration = `${this.goal_name.getBoundingClientRect().width / 40}s`;
} else {
// Toggle animation
this.goal_name.classList.remove("scrollAnim");
this.goal_namedupe.classList.remove("scrollAnim");
this.goal_namedupe.style.display = 'none';
this.scrollwraps[i].classList.remove("fadeLeft");
}
} else {
// Check if element text overflows
if (this.userboxes[i].getBoundingClientRect().width > (this.scrollboxes[i].getBoundingClientRect().width * .65)) {
// Toggle animation
this.userboxes[i].classList.add("scrollAnim");
this.userdupeboxes[i].classList.add("scrollAnim");
this.userdupeboxes[i].style.display = 'inline-block';
this.scrollwraps[i].classList.add("fadeLeft");
// Set animation speed
this.userboxes[i].style.animationDuration = `${this.userboxes[i].getBoundingClientRect().width / 40}s`;
this.userdupeboxes[i].style.animationDuration = `${this.userboxes[i].getBoundingClientRect().width / 40}s`;
} else {
// Toggle animation
this.userboxes[i].classList.remove("scrollAnim");
this.userdupeboxes[i].classList.remove("scrollAnim");
this.userdupeboxes[i].style.display = 'none';
this.scrollwraps[i].classList.remove("fadeLeft");
}
}
}
} }
/** /**
* Bring the display into a standard initial state. * Bring the display into a standard initial state.
*/ */
reset() { reset() {
this.timer.textContent = "00:00"; this.timer.textContent = "88:88";
this.goal_label.textContent = "Next Goal:"; this.goal_label.textContent = "Next Goal:";
this.goal_name.textContent = "Be awesome"; this.goal_name.textContent = "Goal name for the subathon";
this.goal_progress.textContent = "00/00"; this.goal_namedupe.textContent = "Goal name for the subathon";
this.goal_progress.textContent = "1234/1234";
this.topusers_label.textContent = "Leaderboard:"; this.topusers_label.textContent = "Leaderboard:";
this.topusers_user1_num.textContent = "1"; this.topusers_user1_num.textContent = "1";
this.topusers_user1_name.textContent = "Anonymous"; this.topusers_user1_name.textContent = "Username1024";
this.topusers_userdupe1_name.textContent = "Username1024";
this.topusers_user1_score.textContent = "0000";
this.topusers_user2_num.textContent = "2"; this.topusers_user2_num.textContent = "2";
this.topusers_user2_name.textContent = "Anonymous"; this.topusers_user2_name.textContent = "User";
this.topusers_userdupe2_name.textContent = "User";
this.topusers_user2_score.textContent = "0000";
this.topusers_user3_num.textContent = "3"; this.topusers_user3_num.textContent = "3";
this.topusers_user3_name.textContent = "Anonymous"; this.topusers_user3_name.textContent = "Username_Very_Super_Long12";
this.topusers_userdupe3_name.textContent = "Username_Very_Super_Long12";
this.topusers_user3_score.textContent = "0000";
}
// End subathon, change timer color, and show thank you message
finale() {
this.timer.textContent = "00:00";
this.timer.style.color = '#82C8B6';
this.goal_label.textContent = "Completed!";
this.goal_name.textContent = this.thankyou;
this.goal_namedupe.textContent = this.thankyou;
this.animate();
} }
/** /**
@@ -165,9 +277,18 @@ class TimerRenderer {
// Or after we accomplish all goals // Or after we accomplish all goals
this.goal_name.textContent = name; this.goal_name.textContent = name;
this.goal_namedupe.textContent = name;
//this.goal_name.style.animationDuration = `${this.goal_name.getBoundingClientRect().width / 50}s`;
// Bitwise OR done to convert floats to integers if needed // Bitwise OR done to convert floats to integers if needed
this.goal_progress.textContent = String(current | 0) + '/' + String(required | 0) this.goal_progress.textContent = String(current | 0) + '/' + String(required | 0)
// Update the progress bar
if (current / required > .02) {
this.goal_bar.style.maskImage = `linear-gradient(to right, #FC98B3 0%, #FC98B3 ${((current / required) - .02) * 100}%, transparent ${(current / required) * 100}%)`;
} else {
this.goal_bar.style.maskImage = `linear-gradient(to right, #FC98B3 0%, transparent .01%)`;
}
} }
/** /**
@@ -175,6 +296,7 @@ class TimerRenderer {
*/ */
clear_current_goal() { clear_current_goal() {
this.goal_name.textContent = ""; this.goal_name.textContent = "";
//this.goal_namedupe.textContent = "";
this.goal_progress.textContent = ""; this.goal_progress.textContent = "";
this.goal_label.textContent = ""; this.goal_label.textContent = "";
} }
@@ -191,25 +313,40 @@ class TimerRenderer {
if (users.length >= 1) { if (users.length >= 1) {
this.topusers_user1_num.textContent = "1"; this.topusers_user1_num.textContent = "1";
this.topusers_user1_name.textContent = users[0].user_name; this.topusers_user1_name.textContent = users[0].user_name;
this.topusers_userdupe1_name.textContent = users[0].user_name;
this.topusers_user1_score.textContent = Math.round(users[0].amount);
//this.topusers_user1_name.style.animationDuration = `${this.topusers_user1_name.getBoundingClientRect().width / 50}s`;
} else { } else {
this.topusers_user1_num.textContent = ""; this.topusers_user1_num.textContent = "1";
this.topusers_user1_name.textContent = ""; this.topusers_user1_name.textContent = "";
this.topusers_userdupe1_name.textContent = "";
this.topusers_user1_score.textContent = "0000";
} }
if (users.length >= 2) { if (users.length >= 2) {
this.topusers_user2_num.textContent = "2"; this.topusers_user2_num.textContent = "2";
this.topusers_user2_name.textContent = users[1].user_name; this.topusers_user2_name.textContent = users[1].user_name;
this.topusers_userdupe2_name.textContent = users[1].user_name;
this.topusers_user2_score.textContent = Math.round(users[1].amount);
//this.topusers_user2_name.style.animationDuration = `${this.topusers_user2_name.getBoundingClientRect().width / 50}s`;
} else { } else {
this.topusers_user2_num.textContent = ""; this.topusers_user2_num.textContent = "2";
this.topusers_user2_name.textContent = ""; this.topusers_user2_name.textContent = "";
this.topusers_userdupe2_name.textContent = "";
this.topusers_user2_score.textContent = "0000";
} }
if (users.length >= 3) { if (users.length >= 3) {
this.topusers_user3_num.textContent = "3"; this.topusers_user3_num.textContent = "3";
this.topusers_user3_name.textContent = users[2].user_name; this.topusers_user3_name.textContent = users[2].user_name;
this.topusers_userdupe3_name.textContent = users[2].user_name;
this.topusers_user3_score.textContent = Math.round(users[2].amount);
//this.topusers_user3_name.style.animationDuration = `${this.topusers_user3_name.getBoundingClientRect().width / 50}s`;
} else { } else {
this.topusers_user3_num.textContent = ""; this.topusers_user3_num.textContent = "3";
this.topusers_user3_name.textContent = ""; this.topusers_user3_name.textContent = "";
this.topusers_userdupe3_name.textContent = "";
this.topusers_user3_score.textContent = "0000";
} }
} }
@@ -320,6 +457,7 @@ function communicate(websocket) {
) )
); );
renderer.reset(); renderer.reset();
renderer.animate();
}; };
websocket.onmessage = ({ data }) => { websocket.onmessage = ({ data }) => {
@@ -345,6 +483,7 @@ function communicate(websocket) {
timer = null; timer = null;
} }
renderer.reset(); renderer.reset();
renderer.animate();
case "endTimer": case "endTimer":
if (timer != null) { if (timer != null) {
timer.destroying = true; timer.destroying = true;

View File

@@ -1,241 +0,0 @@
:root {
--time-color: #453960;
--details-color: #403060;
--background-color: transparent;
}
* {
box-sizing: border-box;
}
html, body {
height: 100%;
margin: 0;
padding: 0;
font-family: 'Inter', sans-serif;
background-color: var(--background-color);
overflow: hidden;
}
main {
font-family: "Silkscreen", sans-serif;
font-weight: 400;
font-style: normal;
color: #EA4045;
height: 100%;
}
h1 {
margin: 0;
font-size: 3.4em;
color: #404145;
font-weight: normal;
}
h2 {
margin: 0;
font-size: 1.4em;
color: #404145;
font-weight: normal;
}
h3 {
margin: 0;
font-size: 1em;
color: #404145;
font-weight: normal;
}
p {
margin: 0;
font-size: 1.4em;
line-height: 95%;
}
.contentContainer {
height: fit-content;
width: fit-content;
position: relative;
text-align: center;
}
#MainHeart {
max-height: 100vh;
max-width: 100vw;
}
.infoWrap {
container-type: size;
height: 100%;
width: 100%;
position: absolute;
left: 0px;
top: 0px;
display: grid;
grid-template-columns: 56% 34% 1fr;
/*
grid-template-rows: 11% 28% 16% 16% 1fr;
*/
grid-template-rows: 11% 1fr 29%;
place-items: center;
text-wrap: nowrap;
}
.infoGroup {
display: block;
height: 100%;
width: 100%;
grid-column-start: 2;
grid-column-end: 2;
grid-row-start: 2;
grid-row-end: 2;
}
.infoBox {
height: auto;
width: 100%;
/*
display: grid;
grid-template-columns: repeat(1, 1fr);
grid-auto-rows: auto;
place-items: center;
*/
font-size: 4cqh;
}
#InfoBox1 {
/*
justify-self: left;
align-self: stretch;
*/
/*
transform: translate(-8%, 5%);
*/
}
#InfoBox2 {
/*
display: grid;
width: 100%;
justify-self: left;
align-self: stretch;
*/
transform: translate(0%, -12%);
}
#InfoBox3 {
grid-template-columns: 1fr;
grid-template-rows: 1fr 23% 23% 23%;
transform: translate(0%, -16%) scale(1, 1);
/*
justify-self: left;
align-self: stretch;
transform: translate(0%, -32%);
*/
}
#Timer {
margin-top: 10%;
transform: translate(-7.5%, 3%) scale(.95, 1.2);
}
#TimerInfo {
transform: translate(0%, -60%);
/* uni
font-size: 1em;
*/
display: none;
}
#GoalLabel {
transform: translate(5%, 0%) scale(1);
color: #404145;
}
#GoalName {
width: 100%;
transform: translate(8%, -10%) scale(1);
color: #32B993;
text-wrap: nowrap;
overflow: hidden;
mask-image: linear-gradient(to right, black 85%, transparent 100%);
}
#GoalProgressWrap {
width: fit-content;
padding-left: .8cqh;
padding-right: .8cqh;
transform: translate(7%, 0%) scale(1, 1);
border-radius: 3cqh;
border: .4cqh solid;
border-color: #404145;
margin: 0 auto .8cqh auto;
}
#GoalProgress {
transform: translate(0%, -8%) scale(1);
/* uni
font-size: 1.3em;
*/
text-align: center;
/*
font-weight: bold;
*/
}
#TopUsers {
transform: translate(0%, 0%) scale(1);
font-weight: normal;
color: #404145;
/* uni
font-size: 1.1em;
*/
}
.giftUserWrap {
transform: translate(18%, -8%) scale(1, 1);
}
.giftUserRow {
width: 100%;
display: grid;
grid-template-columns: 8% 1fr;
grid-template-rows: 1fr;
text-wrap: nowrap;
overflow: hidden;
text-align: left;
justify-self: left;
text-align: center;
transform: translate(0%, 0%) scale(1, 1);
/* uni
font-size: 1.4em;
*/
/*
line-height: 95%;
*/
}
.giftUserName {
margin-left: 0%;
color: #32B993;
text-align: left;
/*
background-color: blue;
*/
}
#GiftUserName1 {
width: 23.5cqw;
mask-image: linear-gradient(to right, black 80%, transparent 100%);
}
#GiftUserName2 {
width: 21.5cqw;
mask-image: linear-gradient(to right, black 75%, transparent 100%);
/*
background-color: red;
*/
}
#GiftUserName3 {
width: 18cqw;
mask-image: linear-gradient(to right, black 65%, transparent 100%);
}

View File

@@ -1,76 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Silkscreen:wght@400;700&family=VT323&display=swap" rel="stylesheet">
<link href='https://fonts.googleapis.com/css?family=Inter' rel='stylesheet'>
<link rel="stylesheet" href="uniform-font.css" />
<script src="timer.js"></script>
<title>v2 onefont</title>
</head>
<body>
<main>
<div class='contentContainer'>
<img id='MainHeart' src='src/youve_got_mail_whiteheart.png'>
<div class='infoWrap'>
<div class='infoGroup'>
<div class='infoBox' id='InfoBox1'>
<h1 id='Timer'>
00:00
</h1>
<p id='TimerInfo'>
!subathon for details
</p>
</div>
<div class='infoBox' id='InfoBox2'>
<p id='GoalLabel'>
Next Goal:
</p>
<p id='GoalName'>
Discord Watch Party + Puzzles
</p>
<div id='GoalProgressWrap'>
<p id='GoalProgress'>
1234/5678
</p>
</div>
</div>
<div class='infoBox' id='InfoBox3'>
<p id='TopUsers'>
Leaderboard
</p>
<div class='giftUserWrap'>
<div class='giftUserRow' id='GiftUserRow1'>
<p class='giftUserNum' id='GiftUserNum1'>
1
</p>
<p class='giftUserName'id='GiftUserName1'>
Usernamethatisverylong
</p>
</div>
<div class='giftUserRow' id='GiftUserRow2'>
<p class='giftUserNum' id='GiftUserNum2'>
2
</p>
<p class='giftUserName'id='GiftUserName2'>
Usernamethatisverylong
</p>
</div>
<div class='giftUserRow' id='GiftUserRow3'>
<p class='giftUserNum' id='GiftUserNum3'>
3
</p>
<p class='giftUserName'id='GiftUserName3'>
Usernamethatisverylong
</p>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
</body>
</html>