49 lines
1.4 KiB
Vue
49 lines
1.4 KiB
Vue
<template>
|
|
<div
|
|
class="player-progress group relative h-1 w-full cursor-pointer rounded-full bg-white/10 transition-all hover:h-2"
|
|
@click="handleSeek"
|
|
@mousedown="startDrag"
|
|
>
|
|
<div
|
|
class="absolute inset-y-0 left-0 rounded-full bg-primary transition-[width] duration-75"
|
|
:style="{ width: `${store.progress}%` }"
|
|
/>
|
|
<div
|
|
class="absolute top-1/2 h-3 w-3 -translate-y-1/2 rounded-full bg-white opacity-0 shadow-md transition-opacity group-hover:opacity-100"
|
|
:style="{ left: `calc(${store.progress}% - 6px)` }"
|
|
/>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
const store = usePlayerStore()
|
|
const { seek } = useAudioPlayer()
|
|
|
|
function handleSeek(e: MouseEvent) {
|
|
const el = e.currentTarget as HTMLElement
|
|
const rect = el.getBoundingClientRect()
|
|
const percent = (e.clientX - rect.left) / rect.width
|
|
const time = percent * store.duration
|
|
seek(time)
|
|
}
|
|
|
|
function startDrag(e: MouseEvent) {
|
|
const el = e.currentTarget as HTMLElement
|
|
|
|
const onMove = (ev: MouseEvent) => {
|
|
const rect = el.getBoundingClientRect()
|
|
const percent = Math.max(0, Math.min(1, (ev.clientX - rect.left) / rect.width))
|
|
const time = percent * store.duration
|
|
seek(time)
|
|
}
|
|
|
|
const onUp = () => {
|
|
document.removeEventListener('mousemove', onMove)
|
|
document.removeEventListener('mouseup', onUp)
|
|
}
|
|
|
|
document.addEventListener('mousemove', onMove)
|
|
document.addEventListener('mouseup', onUp)
|
|
}
|
|
</script>
|