178 lines
4.8 KiB
Svelte
178 lines
4.8 KiB
Svelte
<script lang="ts">
|
|
import '../app.css';
|
|
import { env } from '$env/dynamic/public';
|
|
import { goto } from '$app/navigation';
|
|
import Settings from './Settings.svelte';
|
|
import { playAudio } from '$lib/stores';
|
|
|
|
let navPaths = [
|
|
{
|
|
name: 'Startseite',
|
|
sprite: `${env.PUBLIC_BASE_PATH}/img/menu-home.png`,
|
|
href: `${env.PUBLIC_BASE_PATH}/`,
|
|
active: false
|
|
},
|
|
{
|
|
name: 'Registrieren',
|
|
sprite: `${env.PUBLIC_BASE_PATH}/img/menu-register.png`,
|
|
href: `${env.PUBLIC_BASE_PATH}/register`,
|
|
active: false
|
|
},
|
|
{
|
|
name: 'Regeln',
|
|
sprite: `${env.PUBLIC_BASE_PATH}/img/menu-rules.png`,
|
|
href: `${env.PUBLIC_BASE_PATH}/rules`,
|
|
active: false
|
|
}
|
|
];
|
|
|
|
let showMenuPermanent = false;
|
|
let menuButtonScrollIndex: number | null = null;
|
|
function onMenuButtonScroll(e: WheelEvent) {
|
|
if (menuButtonScrollIndex == null) {
|
|
if (e.deltaY < 0) {
|
|
menuButtonScrollIndex = navPaths.length - 1;
|
|
} else if (e.deltaY > 0) {
|
|
menuButtonScrollIndex = 0;
|
|
} else {
|
|
menuButtonScrollIndex = navPaths.length - 1;
|
|
}
|
|
} else {
|
|
navPaths[menuButtonScrollIndex].active = false;
|
|
|
|
if (e.deltaY > 0) {
|
|
menuButtonScrollIndex++;
|
|
} else if (e.deltaY < 0) {
|
|
menuButtonScrollIndex--;
|
|
}
|
|
|
|
if (menuButtonScrollIndex > navPaths.length - 1) {
|
|
menuButtonScrollIndex = 0;
|
|
} else if (menuButtonScrollIndex < 0) {
|
|
menuButtonScrollIndex = navPaths.length - 1;
|
|
}
|
|
}
|
|
|
|
navPaths[menuButtonScrollIndex].active = true;
|
|
}
|
|
|
|
let isTouch = false;
|
|
let nav: HTMLDivElement;
|
|
let settings: HTMLDialogElement;
|
|
</script>
|
|
|
|
<svelte:body
|
|
on:keyup={(e) => {
|
|
if (e.key === 'Escape') {
|
|
e.preventDefault();
|
|
if (settings.open) {
|
|
settings.close();
|
|
} else {
|
|
settings.show();
|
|
}
|
|
}
|
|
}}
|
|
on:touchend={(e) => {
|
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
// @ts-ignore
|
|
if (isTouch && !nav.contains(e.target)) showMenuPermanent = false;
|
|
}}
|
|
/>
|
|
|
|
<main>
|
|
<div class="h-screen w-full">
|
|
<slot />
|
|
</div>
|
|
</main>
|
|
<nav>
|
|
<div
|
|
class="fixed bottom-4 right-4 sm:right-[initial] sm:left-4 group/menu-bar flex flex-col-reverse justify-center items-center"
|
|
bind:this={nav}
|
|
>
|
|
<button
|
|
class={isTouch
|
|
? 'btn btn-square relative w-16 h-16'
|
|
: 'btn btn-square group/menu-button relative w-16 h-16'}
|
|
on:click={() => {
|
|
if (!isTouch) {
|
|
let activePath = navPaths.find((path) => path.active);
|
|
if (activePath !== undefined) {
|
|
goto(activePath.href);
|
|
} else if ($playAudio) {
|
|
new Audio(
|
|
`${env.PUBLIC_BASE_PATH}/aud/chest-${showMenuPermanent ? 'close' : 'open'}.mp3`
|
|
).play();
|
|
}
|
|
showMenuPermanent = !showMenuPermanent;
|
|
}
|
|
}}
|
|
on:touchend={() => {
|
|
isTouch = true;
|
|
showMenuPermanent = !showMenuPermanent;
|
|
}}
|
|
on:mouseleave={() => {
|
|
if (menuButtonScrollIndex !== null) {
|
|
navPaths[menuButtonScrollIndex].active = false;
|
|
}
|
|
menuButtonScrollIndex = null;
|
|
}}
|
|
on:wheel|preventDefault={onMenuButtonScroll}
|
|
>
|
|
<img
|
|
class="absolute w-full h-full p-1 pixelated"
|
|
src="{env.PUBLIC_BASE_PATH}/img/menu-button.png"
|
|
alt="menu"
|
|
/>
|
|
<img
|
|
class="opacity-0 transition-opacity delay-50 group-hover/menu-button:opacity-100 absolute w-full h-full p-[3px] pixelated"
|
|
class:opacity-100={isTouch && showMenuPermanent}
|
|
src="{env.PUBLIC_BASE_PATH}/img/selected-frame.png"
|
|
alt="menu hover"
|
|
/>
|
|
</button>
|
|
<div
|
|
class:hidden={!showMenuPermanent}
|
|
class={isTouch ? 'pb-3' : 'group-hover/menu-bar:block pb-3'}
|
|
>
|
|
<ul class="flex flex-col bg-base-200 rounded">
|
|
{#each navPaths as navPath, i}
|
|
<li
|
|
class="flex justify-center tooltip tooltip-left sm:tooltip-right"
|
|
data-tip={navPath.name}
|
|
>
|
|
<a
|
|
class="btn btn-square border-none group/menu-item relative w-[3.5rem] h-[3.5rem] flex justify-center items-center"
|
|
href={navPath.href}
|
|
>
|
|
<div
|
|
style="background-image: url('{env.PUBLIC_BASE_PATH}/img/menu-inventory-bar.png'); background-position: -{i *
|
|
3.5}rem 0;"
|
|
class="block w-full h-full bg-no-repeat bg-horizontal-sprite pixelated"
|
|
/>
|
|
<div class="absolute flex justify-center items-center w-full h-full">
|
|
<img class="w-1/2 h-1/2 pixelated" src={navPath.sprite} alt={navPath.name} />
|
|
</div>
|
|
<img
|
|
class="transition-opacity delay-50 group-hover/menu-item:opacity-100 absolute w-full h-full pixelated scale-110 z-10"
|
|
class:opacity-0={!navPath.active}
|
|
src="{env.PUBLIC_BASE_PATH}/img/selected-frame.png"
|
|
alt="menu hover"
|
|
/>
|
|
</a>
|
|
</li>
|
|
{/each}
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
|
|
<dialog class="modal" bind:this={settings}>
|
|
<form method="dialog" class="modal-box" style="overflow: unset">
|
|
<button class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2">✕</button>
|
|
<Settings />
|
|
</form>
|
|
<form method="dialog" class="modal-backdrop bg-[rgba(0,0,0,.3)]">
|
|
<button>close</button>
|
|
</form>
|
|
</dialog>
|