initiation librodrome

This commit is contained in:
Yvv
2026-02-20 12:55:10 +01:00
commit 35e2897a73
208 changed files with 18951 additions and 0 deletions

View File

@@ -0,0 +1,91 @@
<template>
<canvas
ref="canvasRef"
class="h-12 w-full rounded-lg opacity-60"
/>
</template>
<script setup lang="ts">
const canvasRef = ref<HTMLCanvasElement | null>(null)
const store = usePlayerStore()
const { getAudio } = useAudioPlayer()
let audioContext: AudioContext | null = null
let analyser: AnalyserNode | null = null
let source: MediaElementAudioSourceNode | null = null
let animId: number | null = null
let connected = false
function initAnalyser() {
if (connected || !canvasRef.value) return
try {
const audio = getAudio()
audioContext = new AudioContext()
analyser = audioContext.createAnalyser()
analyser.fftSize = 64
source = audioContext.createMediaElementSource(audio)
source.connect(analyser)
analyser.connect(audioContext.destination)
connected = true
}
catch {
// Web Audio API might not be available
}
}
function draw() {
if (!canvasRef.value || !analyser) {
animId = requestAnimationFrame(draw)
return
}
const canvas = canvasRef.value
const ctx = canvas.getContext('2d')
if (!ctx) return
const bufferLength = analyser.frequencyBinCount
const dataArray = new Uint8Array(bufferLength)
analyser.getByteFrequencyData(dataArray)
canvas.width = canvas.offsetWidth * window.devicePixelRatio
canvas.height = canvas.offsetHeight * window.devicePixelRatio
ctx.scale(window.devicePixelRatio, window.devicePixelRatio)
const width = canvas.offsetWidth
const height = canvas.offsetHeight
ctx.clearRect(0, 0, width, height)
const barWidth = width / bufferLength
const gap = 2
for (let i = 0; i < bufferLength; i++) {
const barHeight = (dataArray[i] / 255) * height
const x = i * (barWidth + gap)
const gradient = ctx.createLinearGradient(0, height, 0, height - barHeight)
gradient.addColorStop(0, 'hsl(12, 76%, 48%)')
gradient.addColorStop(1, 'hsl(36, 80%, 52%)')
ctx.fillStyle = gradient
ctx.fillRect(x, height - barHeight, barWidth, barHeight)
}
animId = requestAnimationFrame(draw)
}
watch(() => store.isPlaying, (playing) => {
if (playing) {
initAnalyser()
if (!animId) draw()
if (audioContext?.state === 'suspended') {
audioContext.resume()
}
}
})
onUnmounted(() => {
if (animId) cancelAnimationFrame(animId)
})
</script>