diff options
| author | Bobby <[email protected]> | 2023-07-12 19:14:06 -0400 |
|---|---|---|
| committer | Bobby <[email protected]> | 2023-07-12 19:14:06 -0400 |
| commit | 2ce0ccb1106c8b21b2e9d99ecf8e0772cbf6344a (patch) | |
| tree | 85a9a1ed34e63b66266cbe4578e39a2670456c3e | |
| parent | 1038819ecd3af7056fba5121ff46a2ac748468f9 (diff) | |
| download | thatcomputerscientist-2ce0ccb1106c8b21b2e9d99ecf8e0772cbf6344a.tar.xz thatcomputerscientist-2ce0ccb1106c8b21b2e9d99ecf8e0772cbf6344a.zip | |
Solitude: Welcome Page Done! Reponds based on `visited` Cookie
| -rw-r--r-- | solitude/urls.py | 2 | ||||
| -rw-r--r-- | solitude/views.py | 14 | ||||
| -rw-r--r-- | static/@solitude/css/welcome/audio.css | 1 | ||||
| -rw-r--r-- | static/@solitude/css/welcome/button.css | 68 | ||||
| -rw-r--r-- | static/@solitude/css/welcome/glitch.css | 574 | ||||
| -rw-r--r-- | static/@solitude/css/welcome/welcome.css | 32 | ||||
| -rw-r--r-- | static/@solitude/js/welcome.js | 113 | ||||
| -rw-r--r-- | templates/@solitude/home.html | 1 | ||||
| -rw-r--r-- | templates/@solitude/welcome.html | 209 |
9 files changed, 801 insertions, 213 deletions
diff --git a/solitude/urls.py b/solitude/urls.py index c4458ebe..68819664 100644 --- a/solitude/urls.py +++ b/solitude/urls.py @@ -5,5 +5,5 @@ from . import views app_name = 'solitude' urlpatterns = [ - path('', views.welcome, name='welcome'), + path('', views.home, name='home'), ] diff --git a/solitude/views.py b/solitude/views.py index da2e06ca..81bc1075 100644 --- a/solitude/views.py +++ b/solitude/views.py @@ -1,3 +1,4 @@ +from django.http import HttpResponse from django.shortcuts import render from .constants.welcome_playlist import WELCOME_TRACKS @@ -6,7 +7,12 @@ import json # Create your views here. TEMPLATE_BASE_PATH = '@solitude' -def welcome(request): - return render(request, f'{TEMPLATE_BASE_PATH}/welcome.html', { - 'playlist_tracks': str(json.dumps(WELCOME_TRACKS)) - }) +def home(request): + is_first_time = request.COOKIES.get('visited', False) + if not is_first_time: + response = render(request, f'{TEMPLATE_BASE_PATH}/welcome.html', { + 'playlist_tracks': str(json.dumps(WELCOME_TRACKS)) + }) + response.set_cookie('visited', True) + return response + return render(request, f'{TEMPLATE_BASE_PATH}/home.html') diff --git a/static/@solitude/css/welcome/audio.css b/static/@solitude/css/welcome/audio.css index ca5b144c..5e0d0c58 100644 --- a/static/@solitude/css/welcome/audio.css +++ b/static/@solitude/css/welcome/audio.css @@ -139,4 +139,3 @@ .track { letter-spacing: 0.1rem; } - diff --git a/static/@solitude/css/welcome/button.css b/static/@solitude/css/welcome/button.css new file mode 100644 index 00000000..48dc5b2e --- /dev/null +++ b/static/@solitude/css/welcome/button.css @@ -0,0 +1,68 @@ +.button { + --offset: 10px; + --border-size: 2px; + display: block; + position: relative; + padding: 1.5em 3em; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + border: 0; + background: transparent; + color: #7679f5; + text-transform: uppercase; + letter-spacing: 0.25em; + outline: none; + cursor: pointer; + font-weight: bold; + border-radius: 0; + box-shadow: inset 0 0 0 var(--border-size) currentcolor; + transition: background 0.8s ease; +} +.button:hover { + background: rgba(100, 0, 0, 0.03); +} +.button__horizontal, +.button__vertical { + position: absolute; + top: var(--horizontal-offset, 0); + right: var(--vertical-offset, 0); + bottom: var(--horizontal-offset, 0); + left: var(--vertical-offset, 0); + transition: transform 0.8s ease; + will-change: transform; +} +.button__horizontal::before, +.button__vertical::before { + content: ""; + position: absolute; + border: inherit; +} +.button__horizontal { + --vertical-offset: calc(var(--offset) * -1); + border-top: var(--border-size) solid currentcolor; + border-bottom: var(--border-size) solid currentcolor; +} +.button__horizontal::before { + top: calc(var(--vertical-offset) - var(--border-size)); + bottom: calc(var(--vertical-offset) - var(--border-size)); + left: calc(var(--vertical-offset) * -1); + right: calc(var(--vertical-offset) * -1); +} +.button:hover .button__horizontal { + transform: scaleX(0); +} +.button__vertical { + --horizontal-offset: calc(var(--offset) * -1); + border-left: var(--border-size) solid currentcolor; + border-right: var(--border-size) solid currentcolor; +} +.button__vertical::before { + top: calc(var(--horizontal-offset) * -1); + bottom: calc(var(--horizontal-offset) * -1); + left: calc(var(--horizontal-offset) - var(--border-size)); + right: calc(var(--horizontal-offset) - var(--border-size)); +} +.button:hover .button__vertical { + transform: scaleY(0); +} diff --git a/static/@solitude/css/welcome/glitch.css b/static/@solitude/css/welcome/glitch.css new file mode 100644 index 00000000..6b8c8987 --- /dev/null +++ b/static/@solitude/css/welcome/glitch.css @@ -0,0 +1,574 @@ +.glitch { + position: relative; + color: #fff; + font-size: 10rem; + font-family: "Share", cursive; +} + +.line:not(:first-child) { + position: absolute; + top: 0; + left: 0; +} +.line:nth-child(1) { + -webkit-animation: clip 3000ms -300ms linear infinite, + glitch1 500ms -80ms linear infinite; + animation: clip 3000ms -300ms linear infinite, + glitch1 500ms -80ms linear infinite; +} +@-webkit-keyframes glitch1 { + 0% { + transform: translateX(0); + } + 80% { + transform: translateX(0); + color: #fff; + } + 85% { + transform: translateX(4px); + color: #4e9a26; + } + 90% { + transform: translateX(5px); + color: #ac1212; + } + 95% { + transform: translateX(0px); + color: #fff; + } + 100% { + transform: translateX(0); + } +} +@keyframes glitch1 { + 0% { + transform: translateX(0); + } + 80% { + transform: translateX(0); + color: #fff; + } + 85% { + transform: translateX(4px); + color: #4e9a26; + } + 90% { + transform: translateX(5px); + color: #ac1212; + } + 95% { + transform: translateX(0px); + color: #fff; + } + 100% { + transform: translateX(0); + } +} +.line:nth-child(2) { + -webkit-animation: clip 3000ms -600ms linear infinite, + glitch2 500ms -433ms linear infinite; + animation: clip 3000ms -600ms linear infinite, + glitch2 500ms -433ms linear infinite; +} +@-webkit-keyframes glitch2 { + 0% { + transform: translateX(0); + } + 80% { + transform: translateX(0); + color: #fff; + } + 85% { + transform: translateX(3px); + color: #4e9a26; + } + 90% { + transform: translateX(-3px); + color: #ac1212; + } + 95% { + transform: translateX(4px); + color: #fff; + } + 100% { + transform: translateX(0); + } +} +@keyframes glitch2 { + 0% { + transform: translateX(0); + } + 80% { + transform: translateX(0); + color: #fff; + } + 85% { + transform: translateX(3px); + color: #4e9a26; + } + 90% { + transform: translateX(-3px); + color: #ac1212; + } + 95% { + transform: translateX(4px); + color: #fff; + } + 100% { + transform: translateX(0); + } +} +.line:nth-child(3) { + -webkit-animation: clip 3000ms -900ms linear infinite, + glitch3 500ms -664ms linear infinite; + animation: clip 3000ms -900ms linear infinite, + glitch3 500ms -664ms linear infinite; +} +@-webkit-keyframes glitch3 { + 0% { + transform: translateX(0); + } + 80% { + transform: translateX(0); + color: #fff; + } + 85% { + transform: translateX(4px); + color: #4e9a26; + } + 90% { + transform: translateX(5px); + color: #ac1212; + } + 95% { + transform: translateX(-2px); + color: #fff; + } + 100% { + transform: translateX(0); + } +} +@keyframes glitch3 { + 0% { + transform: translateX(0); + } + 80% { + transform: translateX(0); + color: #fff; + } + 85% { + transform: translateX(4px); + color: #4e9a26; + } + 90% { + transform: translateX(5px); + color: #ac1212; + } + 95% { + transform: translateX(-2px); + color: #fff; + } + 100% { + transform: translateX(0); + } +} +.line:nth-child(4) { + -webkit-animation: clip 3000ms -1200ms linear infinite, + glitch4 500ms -276ms linear infinite; + animation: clip 3000ms -1200ms linear infinite, + glitch4 500ms -276ms linear infinite; +} +@-webkit-keyframes glitch4 { + 0% { + transform: translateX(0); + } + 80% { + transform: translateX(0); + color: #fff; + } + 85% { + transform: translateX(-3px); + color: #4e9a26; + } + 90% { + transform: translateX(2px); + color: #ac1212; + } + 95% { + transform: translateX(-2px); + color: #fff; + } + 100% { + transform: translateX(0); + } +} +@keyframes glitch4 { + 0% { + transform: translateX(0); + } + 80% { + transform: translateX(0); + color: #fff; + } + 85% { + transform: translateX(-3px); + color: #4e9a26; + } + 90% { + transform: translateX(2px); + color: #ac1212; + } + 95% { + transform: translateX(-2px); + color: #fff; + } + 100% { + transform: translateX(0); + } +} +.line:nth-child(5) { + -webkit-animation: clip 3000ms -1500ms linear infinite, + glitch5 500ms -180ms linear infinite; + animation: clip 3000ms -1500ms linear infinite, + glitch5 500ms -180ms linear infinite; +} +@-webkit-keyframes glitch5 { + 0% { + transform: translateX(0); + } + 80% { + transform: translateX(0); + color: #fff; + } + 85% { + transform: translateX(-2px); + color: #4e9a26; + } + 90% { + transform: translateX(-4px); + color: #ac1212; + } + 95% { + transform: translateX(2px); + color: #fff; + } + 100% { + transform: translateX(0); + } +} +@keyframes glitch5 { + 0% { + transform: translateX(0); + } + 80% { + transform: translateX(0); + color: #fff; + } + 85% { + transform: translateX(-2px); + color: #4e9a26; + } + 90% { + transform: translateX(-4px); + color: #ac1212; + } + 95% { + transform: translateX(2px); + color: #fff; + } + 100% { + transform: translateX(0); + } +} +.line:nth-child(6) { + -webkit-animation: clip 3000ms -1800ms linear infinite, + glitch6 500ms -954ms linear infinite; + animation: clip 3000ms -1800ms linear infinite, + glitch6 500ms -954ms linear infinite; +} +@-webkit-keyframes glitch6 { + 0% { + transform: translateX(0); + } + 80% { + transform: translateX(0); + color: #fff; + } + 85% { + transform: translateX(-3px); + color: #4e9a26; + } + 90% { + transform: translateX(-4px); + color: #ac1212; + } + 95% { + transform: translateX(1px); + color: #fff; + } + 100% { + transform: translateX(0); + } +} +@keyframes glitch6 { + 0% { + transform: translateX(0); + } + 80% { + transform: translateX(0); + color: #fff; + } + 85% { + transform: translateX(-3px); + color: #4e9a26; + } + 90% { + transform: translateX(-4px); + color: #ac1212; + } + 95% { + transform: translateX(1px); + color: #fff; + } + 100% { + transform: translateX(0); + } +} +.line:nth-child(7) { + -webkit-animation: clip 3000ms -2100ms linear infinite, + glitch7 500ms -377ms linear infinite; + animation: clip 3000ms -2100ms linear infinite, + glitch7 500ms -377ms linear infinite; +} +@-webkit-keyframes glitch7 { + 0% { + transform: translateX(0); + } + 80% { + transform: translateX(0); + color: #fff; + } + 85% { + transform: translateX(2px); + color: #4e9a26; + } + 90% { + transform: translateX(-1px); + color: #ac1212; + } + 95% { + transform: translateX(-1px); + color: #fff; + } + 100% { + transform: translateX(0); + } +} +@keyframes glitch7 { + 0% { + transform: translateX(0); + } + 80% { + transform: translateX(0); + color: #fff; + } + 85% { + transform: translateX(2px); + color: #4e9a26; + } + 90% { + transform: translateX(-1px); + color: #ac1212; + } + 95% { + transform: translateX(-1px); + color: #fff; + } + 100% { + transform: translateX(0); + } +} +.line:nth-child(8) { + -webkit-animation: clip 3000ms -2400ms linear infinite, + glitch8 500ms -104ms linear infinite; + animation: clip 3000ms -2400ms linear infinite, + glitch8 500ms -104ms linear infinite; +} +@-webkit-keyframes glitch8 { + 0% { + transform: translateX(0); + } + 80% { + transform: translateX(0); + color: #fff; + } + 85% { + transform: translateX(1px); + color: #4e9a26; + } + 90% { + transform: translateX(-2px); + color: #ac1212; + } + 95% { + transform: translateX(4px); + color: #fff; + } + 100% { + transform: translateX(0); + } +} +@keyframes glitch8 { + 0% { + transform: translateX(0); + } + 80% { + transform: translateX(0); + color: #fff; + } + 85% { + transform: translateX(1px); + color: #4e9a26; + } + 90% { + transform: translateX(-2px); + color: #ac1212; + } + 95% { + transform: translateX(4px); + color: #fff; + } + 100% { + transform: translateX(0); + } +} +.line:nth-child(9) { + -webkit-animation: clip 3000ms -2700ms linear infinite, + glitch9 500ms -606ms linear infinite; + animation: clip 3000ms -2700ms linear infinite, + glitch9 500ms -606ms linear infinite; +} +@-webkit-keyframes glitch9 { + 0% { + transform: translateX(0); + } + 80% { + transform: translateX(0); + color: #fff; + } + 85% { + transform: translateX(1px); + color: #4e9a26; + } + 90% { + transform: translateX(-4px); + color: #ac1212; + } + 95% { + transform: translateX(2px); + color: #fff; + } + 100% { + transform: translateX(0); + } +} +@keyframes glitch9 { + 0% { + transform: translateX(0); + } + 80% { + transform: translateX(0); + color: #fff; + } + 85% { + transform: translateX(1px); + color: #4e9a26; + } + 90% { + transform: translateX(-4px); + color: #ac1212; + } + 95% { + transform: translateX(2px); + color: #fff; + } + 100% { + transform: translateX(0); + } +} +.line:nth-child(10) { + -webkit-animation: clip 3000ms -3000ms linear infinite, + glitch10 500ms -560ms linear infinite; + animation: clip 3000ms -3000ms linear infinite, + glitch10 500ms -560ms linear infinite; +} +@-webkit-keyframes glitch10 { + 0% { + transform: translateX(0); + } + 80% { + transform: translateX(0); + color: #fff; + } + 85% { + transform: translateX(-1px); + color: #4e9a26; + } + 90% { + transform: translateX(1px); + color: #ac1212; + } + 95% { + transform: translateX(1px); + color: #fff; + } + 100% { + transform: translateX(0); + } +} +@keyframes glitch10 { + 0% { + transform: translateX(0); + } + 80% { + transform: translateX(0); + color: #fff; + } + 85% { + transform: translateX(-1px); + color: #4e9a26; + } + 90% { + transform: translateX(1px); + color: #ac1212; + } + 95% { + transform: translateX(1px); + color: #fff; + } + 100% { + transform: translateX(0); + } +} + +@-webkit-keyframes clip { + 0% { + -webkit-clip-path: polygon(0 100%, 100% 100%, 100% 120%, 0 120%); + clip-path: polygon(0 100%, 100% 100%, 100% 120%, 0 120%); + } + 100% { + -webkit-clip-path: polygon(0 -20%, 100% -20%, 100% 0%, 0 0); + clip-path: polygon(0 -20%, 100% -20%, 100% 0%, 0 0); + } +} + +@keyframes clip { + 0% { + -webkit-clip-path: polygon(0 100%, 100% 100%, 100% 120%, 0 120%); + clip-path: polygon(0 100%, 100% 100%, 100% 120%, 0 120%); + } + 100% { + -webkit-clip-path: polygon(0 -20%, 100% -20%, 100% 0%, 0 0); + clip-path: polygon(0 -20%, 100% -20%, 100% 0%, 0 0); + } +} diff --git a/static/@solitude/css/welcome/welcome.css b/static/@solitude/css/welcome/welcome.css index 22a1a747..b4fcde6c 100644 --- a/static/@solitude/css/welcome/welcome.css +++ b/static/@solitude/css/welcome/welcome.css @@ -11,6 +11,8 @@ */ @import url("https://fonts.googleapis.com/css2?family=Handlee&family=Poppins:wght@400&family=Share:wght@700&display=swap"); @import url(audio.css); +@import url(button.css); +@import url(glitch.css); :root { --button-height: 0.5rem; --button-color: #edd; @@ -42,7 +44,6 @@ min-height: 100%; height: 100%; width: 100%; - background-color: rgba(0, 0, 0, 0.15); z-index: -99; } @@ -52,6 +53,14 @@ align-items: center; justify-content: center; min-height: 100vh; + background: repeating-linear-gradient( + 0deg, + #0e0d0e77 25%, + #0e0d0e77 50%, + #17181977 50%, + #17181977 75% + ); + background-size: 10px 10px; } .cwrapper { @@ -78,21 +87,8 @@ p { margin-top: 10rem; } -.description { - font-family: "Share", sans-serif; - font-size: 1rem; - margin-top: -4rem; - letter-spacing: 0.1rem; +@media only screen and (max-width: 600px) { + .glitch { + font-size: 5rem; + } } - -.text-box { - font-family: "Share", cursive; -} - -.text-box > h1 { - margin: 0; - font-size: 10rem; - color: rgb(255 255 255 / 60%); - padding: .5em; -} - diff --git a/static/@solitude/js/welcome.js b/static/@solitude/js/welcome.js new file mode 100644 index 00000000..d8921075 --- /dev/null +++ b/static/@solitude/js/welcome.js @@ -0,0 +1,113 @@ +Object.defineProperty(Array.prototype, "shuffle", { + value: function () { + for (let i = this.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [this[i], this[j]] = [this[j], this[i]]; + } + return this; + }, +}); + +const tracks = Object.entries(playlistTracks) + .map((track) => track[1]) + .shuffle(); + +const controls = document.querySelector(".controls"); +const audio = document.querySelector("#audio"); +const trackTitle = document.querySelector("#track-title"); +const trackArtist = document.querySelector("#track-artist"); +const albumArt = document.querySelector("#album-art"); +const minElap = document.querySelector("#min-elap"); +const secElap = document.querySelector("#sec-elap"); +const minDur = document.querySelector("#min-dur"); +const secDur = document.querySelector("#sec-dur"); + +let currentTrack = 0; + +const loadAudio = new Promise((resolve, reject) => { + audio.addEventListener("canplaythrough", () => { + resolve(audio); + }); +}); + +async function playAudio() { + audio.src = tracks[currentTrack].location; + const duration = audio.duration; + audio.play().catch((e) => { + window.addEventListener( + "click", + () => { + controls.click(); + audio.play(); + }, + { once: true } + ); + }); + return audio; +} + +function pauseAudio() { + audio.pause(); +} + +function nextTrack() { + currentTrack = (currentTrack + 1) % tracks.length; + audio.currentTime = 0; + playTrack(); +} + +function playTrack() { + const track = tracks[currentTrack]; + trackTitle.textContent = track.title; + trackArtist.textContent = track.artist; + albumArt.src = track.cover_art; + playAudio().then((audio) => { + audio.addEventListener("ended", nextTrack); + }); +} + +function updateIntervals() { + const duration = audio.duration; + const currentTime = audio.currentTime; + const elapsed = Math.floor(currentTime); + const total = Math.floor(duration); + const minutesElapsed = Math.floor(elapsed / 60); + const secondsElapsed = elapsed % 60; + const minutesTotal = Math.floor(total / 60) || 0; + const secondsTotal = total % 60 || 0; + minElap.textContent = + minutesElapsed < 10 ? `0${minutesElapsed}` : minutesElapsed; + secElap.textContent = + secondsElapsed < 10 ? `0${secondsElapsed}` : secondsElapsed; + minDur.textContent = minutesTotal < 10 ? `0${minutesTotal}` : minutesTotal; + secDur.textContent = secondsTotal < 10 ? `0${secondsTotal}` : secondsTotal; +} + +function togglePlayPause() { + const buttons = Array.from(this.children); + let triggeredButton; + buttons.forEach((button) => { + if (!button.classList.contains("hidden")) { + triggeredButton = button; + } + button.classList.toggle("hidden"); + }); + signalTrigger(triggeredButton); +} + +function signalTrigger(button) { + const role = button.getAttribute("role"); + switch (role) { + case "play": + playAudio(); + break; + case "pause": + pauseAudio(); + break; + } +} + +audio.currentTime = 0; +controls.addEventListener("click", togglePlayPause); +audio.addEventListener("timeupdate", updateIntervals); +playTrack(); diff --git a/templates/@solitude/home.html b/templates/@solitude/home.html new file mode 100644 index 00000000..de6f7fe1 --- /dev/null +++ b/templates/@solitude/home.html @@ -0,0 +1 @@ +<h1>Welcome to Solitude</h1>
\ No newline at end of file diff --git a/templates/@solitude/welcome.html b/templates/@solitude/welcome.html index 9c07dad2..ba4e47d5 100644 --- a/templates/@solitude/welcome.html +++ b/templates/@solitude/welcome.html @@ -16,12 +16,23 @@ </div><div id="cover-wrapper"> <div id="welcome-content"> <div class="cwrapper"> - <div class="text-box"> - <h1>THE SOLITUDE</h1> + <div class="glitch"> + <div class="line">the solitude</div> + <div class="line">the solitude</div> + <div class="line">the solitude</div> + <div class="line">the solitude</div> + <div class="line">the solitude</div> + <div class="line">the solitude</div> + <div class="line">the solitude</div> + <div class="line">the solitude</div> + <div class="line">the solitude</div> </div> - </div> - <p class="description"></p> - <button id="enter">Enter The Solitude!</button> + </div> + <button class="button" style="margin-top: 1rem;" onclick="window.location.reload();"> + Enter Shifoo's Solitude... + <div class="button__horizontal"></div> + <div class="button__vertical"></div> + </button> <div id="welcome-playlist-player"> <div class="controls"> <button role="play" id="playButton" class="play"></button> @@ -48,190 +59,10 @@ </div> </div> <script> - Object.defineProperty(Array.prototype, 'shuffle', { - value: function() { - for (let i = this.length - 1; i > 0; i--) { - const j = Math.floor(Math.random() * (i + 1)); - [this[i], this[j]] = [this[j], this[i]]; - } - return this; - } - }); - - const playlistTracks = JSON.parse("{{ playlist_tracks }}".replace(/"/g, '"')); - const tracks = Object.entries(playlistTracks).map(track => track[1]).shuffle(); - - const controls = document.querySelector('.controls'); - const audio = document.querySelector('#audio'); - const trackTitle = document.querySelector('#track-title'); - const trackArtist = document.querySelector('#track-artist'); - const albumArt = document.querySelector('#album-art'); - const minElap = document.querySelector('#min-elap'); - const secElap = document.querySelector('#sec-elap'); - const minDur = document.querySelector('#min-dur'); - const secDur = document.querySelector('#sec-dur'); - - let currentTrack = 0; - - const loadAudio = new Promise((resolve, reject) => { - audio.addEventListener('canplaythrough', () => { - resolve(audio); - }); - }); - - async function playAudio () { - audio.src = tracks[currentTrack].location; - const duration = audio.duration; - audio.play().catch(e => { - window.addEventListener('click', () => { - controls.click(); - audio.play(); - }, { once: true }); - }); - return audio; - } - - function pauseAudio () { - audio.pause(); - } - - function nextTrack () { - currentTrack = (currentTrack + 1) % tracks.length; - audio.currentTime = 0; - playTrack(); - } - - function playTrack() { - const track = tracks[currentTrack]; - trackTitle.textContent = track.title; - trackArtist.textContent = track.artist; - albumArt.src = track.cover_art; - playAudio().then(audio => { - audio.addEventListener('ended', nextTrack); - }); - } - - function updateIntervals() { - const duration = audio.duration; - const currentTime = audio.currentTime; - const elapsed = Math.floor(currentTime); - const total = Math.floor(duration); - const minutesElapsed = Math.floor(elapsed / 60); - const secondsElapsed = elapsed % 60; - const minutesTotal = Math.floor(total / 60) || 0; - const secondsTotal = total % 60 || 0; - minElap.textContent = minutesElapsed < 10 ? `0${minutesElapsed}` : minutesElapsed; - secElap.textContent = secondsElapsed < 10 ? `0${secondsElapsed}` : secondsElapsed; - minDur.textContent = minutesTotal < 10 ? `0${minutesTotal}` : minutesTotal; - secDur.textContent = secondsTotal < 10 ? `0${secondsTotal}` : secondsTotal; - } - - function togglePlayPause () { - const buttons = Array.from(this.children); - let triggeredButton; - buttons.forEach(button => { - if (!button.classList.contains('hidden')) { - triggeredButton = button; - } - button.classList.toggle('hidden') - }); - signalTrigger(triggeredButton); - }; - - function signalTrigger (button) { - const role = button.getAttribute('role'); - switch (role) { - case 'play': - playAudio(); - break; - case 'pause': - pauseAudio(); - break; - } - } - - audio.currentTime = 0; - controls.addEventListener('click', togglePlayPause); - audio.addEventListener('timeupdate', updateIntervals); - - playTrack(); - - class TextScramble { - constructor(el) { - this.el = el - this.chars = '!<>-_\\/[]{}—=+*^?#________' - this.update = this.update.bind(this) - } - setText(newText) { - const oldText = this.el.innerText - const length = Math.max(oldText.length, newText.length) - const promise = new Promise((resolve) => this.resolve = resolve) - this.queue = [] - for (let i = 0; i < length; i++) { - const from = oldText[i] || '' - const to = newText[i] || '' - const start = Math.floor(Math.random() * 40) - const end = start + Math.floor(Math.random() * 40) - this.queue.push({ from, to, start, end }) - } - cancelAnimationFrame(this.frameRequest) - this.frame = 0 - this.update() - return promise - } - update() { - let output = '' - let complete = 0 - for (let i = 0, n = this.queue.length; i < n; i++) { - let { from, to, start, end, char } = this.queue[i] - if (this.frame >= end) { - complete++ - output += to - } else if (this.frame >= start) { - if (!char || Math.random() < 0.28) { - char = this.randomChar() - this.queue[i].char = char - } - output += `<span class="dud">${char}</span>` - } else { - output += from - } - } - this.el.innerHTML = output - if (complete === this.queue.length) { - this.resolve() - } else { - this.frameRequest = requestAnimationFrame(this.update) - this.frame++ - } - } - randomChar() { - return this.chars[Math.floor(Math.random() * this.chars.length)] - } - } - - const phrases = [ - 'Welcome to Shifoo\'s Solitude', - 'A Web Dungeon located beyond the Dark Hollows of the Endless Information SuperHighway', - 'a dark yet tranquil place where all questions end, curiosity begins, the mind awakens,', - 'and one\'s journey begins anew in the solitude of a serene mind!', - 'The Solitude awaits your arrival...' - ] - - const el = document.querySelector('.description') - const fx = new TextScramble(el) - - let counter = 0 - const next = () => { - fx.setText(phrases[counter]).then(() => { - setTimeout(next, 3200) - }) - counter = (counter + 1) % phrases.length - } - - next() - + const playlistTracks = JSON.parse( + "{{ playlist_tracks }}".replace(/"/g, '"') + ); </script> - + <script src="{% static '@solitude/js/welcome.js' %}"></script> </body> </html> |
