summaryrefslogtreecommitdiff
path: root/static
diff options
context:
space:
mode:
Diffstat (limited to 'static')
-rw-r--r--static/main.js61
-rw-r--r--static/style.css160
2 files changed, 214 insertions, 7 deletions
diff --git a/static/main.js b/static/main.js
index 144254f..183b117 100644
--- a/static/main.js
+++ b/static/main.js
@@ -6,10 +6,10 @@ function getContext() {
return _context;
}
-function loadSample(url) {
- return fetch(url)
- .then((response) => response.arrayBuffer())
- .then((buffer) => getContext().decodeAudioData(buffer));
+async function loadSample(url) {
+ const res = await fetch(url);
+ const buffer = res.arrayBuffer();
+ return getContext().decodeAudioData(buffer);
}
function playSoundSample(sample, sampleNote, noteToPlay) {
@@ -20,3 +20,56 @@ function playSoundSample(sample, sampleNote, noteToPlay) {
source.connect(ctx.destination);
source.start(0);
}
+
+function sigmoid(x) {
+ return 1 / (1 + Math.exp(-x));
+}
+
+function drawNoteLines(canvas) {
+ const ctx = canvas.getContext("2d");
+
+ let clicks = [];
+
+ function render() {
+ const W = 256;
+ const H = 512;
+ ctx.clearRect(0, 0, W, H);
+
+ const L = 1.0;
+ ctx.lineWidth = L;
+ ctx.strokeStyle = "#ccc";
+
+ for (let note = 0; note <= 12; note++) {
+ ctx.beginPath();
+ const y = (note / 12) * (H - L) + L / 2;
+ ctx.moveTo(0, y);
+ ctx.lineTo(W, y);
+ ctx.stroke();
+ }
+
+ let now = Date.now();
+ const R = 10.0;
+ for (const [x, y, t] of clicks) {
+ ctx.beginPath();
+ ctx.arc(x - R, y - R, 10, 0, 2 * Math.PI);
+ const tt = (now - t) / 1000; // [0, 1]
+ const alpha = sigmoid(5 - 10 * tt);
+ ctx.fillStyle = `rgb(0, 99, 228, ${alpha})`;
+ ctx.fill();
+ }
+
+ clicks = clicks.filter((o) => now < o[2] + 1_000);
+ if (clicks.length > 0) {
+ requestAnimationFrame(render);
+ }
+ }
+ render();
+
+ canvas.addEventListener("mousedown", (e) => {
+ const { layerX, layerY } = e;
+ clicks.push([layerX, layerY, Date.now()]);
+ render();
+ });
+}
+
+window.drawNoteLines = drawNoteLines;
diff --git a/static/style.css b/static/style.css
index 3b9ba9d..3dac7a4 100644
--- a/static/style.css
+++ b/static/style.css
@@ -1,18 +1,172 @@
+@import url("https://fonts.googleapis.com/css2?family=Chakra+Petch:ital,wght@0,300;0,400;0,500;0,600;0,700;1,300;1,400;1,500;1,600;1,700&display=swap");
+
:root {
+ font-family: "Chakra Petch", serif;
+}
+
+* {
+ font-family: "Chakra Petch", serif;
+ padding: 0;
+ margin: 0;
}
body {
+ background: hsl(214 100% 44.7%);
+ color: white;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+h1 {
+ font-size: 48px;
+ text-align: center;
+}
+
+button {
+ background: hsl(214 100% 100%);
+ color: hsl(214 100% 15%);
+ padding: 12px 24px;
+ border: none;
+ border-radius: 4px;
+ font-size: 16px;
+
+ &:hover {
+ background: hsl(214 100% 95%);
+ cursor: pointer;
+ }
+}
+
+form {
+ display: flex;
+ flex-direction: row;
+ gap: 10px;
+}
+
+input:not([type]) {
+ padding: 4px 8px;
+ border: none;
+ border-radius: 4px;
+ font-size: 16px;
+
+ &:focus {
+ outline: none;
+ }
+}
+
+input[type="submit"] {
+ background: white;
+ padding: 4px 8px;
+ border: none;
+ border-radius: 4px;
+ font-size: 16px;
+
+ &:hover {
+ background: #f0f0f0;
+ cursor: pointer;
+ }
+}
+
+body > section {
+ padding: 48px 24px;
+ display: flex;
+ flex-direction: column;
+ gap: 10px;
+
+ align-items: center;
+}
+
+canvas {
+ background: white;
+ box-shadow: 0 0 10px 4px #00000080;
+ padding: 10px;
+ border-radius: 5px;
+}
+
+footer {
+ border-top: 1px solid #00000020;
+ padding: 24px;
+ text-align: center;
+}
+
+a {
+ color: #e1edfe;
+ &:visited {
+ color: #e1edfe;
+ }
+}
+
+.main-page {
+ min-width: 30rem;
+ max-width: 50vw;
+}
+
+.games-list {
+ list-style: none;
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+
+ padding-bottom: 24px;
+
+ li {
+ display: flex;
+ a {
+ flex: 1;
+ border-radius: 20px;
+ padding: 4px 16px;
+ background: #ffffff;
+ text-decoration: none;
+ &:hover {
+ background: #f0f8ff;
+ }
+ color: #333;
+ &:visited {
+ color: #333;
+ }
+ }
+ }
+}
+
+.leaderboard {
+ font-size: 20px;
+ li {
+ margin-left: 20px;
+ }
+ padding-bottom: 36px;
}
#guesslist {
list-style: none;
+ display: flex;
+ flex-direction: row;
+ gap: 10px;
+ min-width: 50vw;
+ flex-wrap: wrap;
+
+ li {
+ border-radius: 4px;
+ padding: 4px 8px;
+
+ background: white;
+ color: black;
+ }
+
[data-accept="none"] {
- background: #aaa;
+ &::before {
+ content: "❓ ";
+ }
}
[data-accept="true"] {
- background: #00ff00;
+ background: #d9ffd9;
+ &::before {
+ content: "✅ ";
+ }
}
[data-accept="false"] {
- background: #ff0000;
+ background: #ffc0c0;
+ &::before {
+ content: "❌ ";
+ }
}
}