composer / source /ui /src /lib /Notes.svelte
Ron Au
fix: Remove placeholders
339a63f
raw
history blame
2.87 kB
<script lang="ts">
import { fade } from 'svelte/transition';
import { audioBlob, notesImage } from './stores';
let currentTime: number;
let duration: number;
let paused = true;
let container: HTMLDivElement;
let visualisation: HTMLImageElement;
$: imageWidth = visualisation && visualisation.clientWidth;
let sectionWidth: number;
$: if ($audioBlob || currentTime || duration || !paused) {
imageWidth = visualisation && visualisation.clientWidth;
}
const mouseMove = (event: MouseEvent): void => {
if (!duration) {
return;
}
if (!event.buttons) {
return;
}
const { left, right } = container.getBoundingClientRect();
currentTime = (duration * (event.clientX - left)) / (right - left);
};
const touchMove = (event: TouchEvent): void => {
if (!duration) {
return;
}
const { left, right } = container.getBoundingClientRect();
currentTime = (duration * (event.touches[0].clientX - left)) / (right - left);
};
const handleKeydown = (e: KeyboardEvent): void => {
if (e.code === 'Space') {
paused = !paused;
}
};
</script>
<svelte:window on:keydown={handleKeydown} on:resize={() => (imageWidth = visualisation && visualisation.clientWidth)} />
{#if $audioBlob}
<section bind:clientWidth={sectionWidth} transition:fade>
<div
class="container"
bind:this={container}
on:mousemove={mouseMove}
on:touchmove|preventDefault={touchMove}
style:width={Math.min(imageWidth, sectionWidth) + 'px'}
>
<img
class="visualisation"
src={$notesImage}
alt="MIDI notes of composition"
draggable="false"
bind:this={visualisation}
on:click={() => (paused = !paused)}
/>
<audio bind:currentTime bind:duration bind:paused src={$audioBlob} />
<div class="handle" style:transform="translateX({imageWidth * (currentTime / duration)}px)" />
{#if paused}
<img
class="play"
src="play.svg"
alt="Play button"
draggable="false"
transition:fade
on:click={() => (paused = !paused)}
/>
{/if}
</div>
</section>
{/if}
<style>
section {
border: 2px solid hsl(0 0% 80%);
border-radius: 0.375rem;
padding: 1rem;
}
.container {
position: relative;
padding: 1rem;
margin: auto;
}
.visualisation {
display: block;
margin: auto;
cursor: pointer;
}
audio {
width: 100%;
margin: 1rem auto;
}
.play {
position: absolute;
left: 50%;
top: 50%;
width: 20%;
aspect-ratio: 1 / 1;
transform: translate(-50%, -60%);
filter: drop-shadow(0 0 5px black);
cursor: pointer;
}
.handle {
position: absolute;
left: 0;
top: 0;
height: 100%;
width: 0.2rem;
margin-left: 1rem;
border-radius: 0.1rem;
background-color: white;
cursor: pointer;
}
@media (min-width: 600px) {
.visualisation {
max-width: 512px;
}
}
</style>