1
0
Fork 0
mirror of https://github.com/mat-1/matdoesdev.git synced 2025-08-02 14:46:04 +00:00
matdoesdev/src/routes/retro/MusicPlayer.svelte

167 lines
3.5 KiB
Svelte

<script lang="ts">
import Forward from './icons/Forward.svelte'
import Backward from './icons/Backward.svelte'
import Pause from './icons/Pause.svelte'
import Play from './icons/Play.svelte'
import { browser } from '$app/environment'
let musicPlayerEl: HTMLAudioElement | undefined = $state(undefined)
let playing = $state(false)
let volume = $state(50)
const SONGS = `2 Mello - Mirror Temple (Mirror Magic Mix)
C418 - Biome Party
Epic Mountain - Stellar Engine
Garoad - Every Day is Night
Garoad - Good For Health, Bad For Education
Garoad - Heart Of The City
HOME - 17
Ian Taylor - Autumn Voyage
Kupla - Noir
Kuraine - Summit (No More Running Mix)
Makeup and Vanity Set - Search the Night
Peppsen - Blueprint
Peppsen - Split
Toby Fox - A CYBER'S WORLD?
VØJ - Moonlit`.split('\n')
function shuffleArray(array: any[]) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1))
var temp = array[i]
array[i] = array[j]
array[j] = temp
}
}
if (browser) shuffleArray(SONGS)
let currentSongIndex = $state(0)
let currentSong = $derived(SONGS[currentSongIndex])
let currentSong_: string | null = $state(null)
$effect(() => {
if (musicPlayerEl) {
musicPlayerEl.volume = volume / 100
}
})
$effect(() => {
if (musicPlayerEl) {
if (playing) musicPlayerEl.play()
else musicPlayerEl.pause()
}
})
$effect(() => {
if (musicPlayerEl) {
if (currentSong_ !== currentSong) {
const newSrc = `/retro/music/${currentSong.replace(/\?/g, '')}.mp3`
musicPlayerEl.src = newSrc
musicPlayerEl.load()
currentSong_ = currentSong
}
}
})
function nextSong() {
currentSongIndex = (currentSongIndex + 1) % SONGS.length
musicPlayerEl?.play()
}
function prevSong() {
currentSongIndex = (currentSongIndex - 1 + SONGS.length) % SONGS.length
musicPlayerEl?.play()
}
</script>
<audio bind:this={musicPlayerEl} onended={nextSong}></audio>
<table class="music-player" style={musicPlayerEl ? '' : 'display: none'}>
<tbody>
<tr>
<td>
<button onclick={prevSong}>
<Backward />
</button>
</td>
<td>
<button onclick={() => (playing = !playing)}>
{#if playing}
<Pause />
{:else}
<Play />
{/if}
</button>
</td>
<td>
<button onclick={nextSong}>
<Forward />
</button>
</td>
<td>
<span class="song-name-container">
<span class="song-name">Now playing: {playing ? currentSong : 'Nothing'}</span>
</span>
</td>
<td>
<input type="range" min="0" max="100" class="volume-slider" bind:value={volume} />
</td>
</tr>
</tbody>
</table>
<style>
.music-player {
position: fixed;
bottom: 0;
right: 0;
background: linear-gradient(0deg, #600, #800);
border: 1px solid #000;
width: 300px;
}
button {
border: none;
background: none;
padding: 0;
margin: 0;
cursor: pointer;
width: 2em;
height: 2em;
fill: #fff;
filter: drop-shadow(2px 2px 2px rgba(0, 0, 0, 0.5));
/* vertically center */
display: flex;
align-items: center;
justify-content: center;
/* reset styles from default stylesheet */
box-shadow: none;
}
button:hover {
background-color: transparent;
}
.song-name-container {
box-shadow: inset 2px 2px 2px 2px rgba(0, 0, 0, 0.3);
padding: 0.3em;
font-family: sans-serif;
border-radius: 0.2em;
width: 300px;
display: block;
overflow: auto;
}
.song-name {
text-shadow: 2px 2px 2px rgba(0, 0, 0, 0.5);
white-space: nowrap;
}
.volume-slider {
width: 100px;
}
</style>