This commit is contained in:
wvffle 2022-11-06 09:58:15 +00:00
parent 7b1cf7509f
commit 839a80b3ac
3 changed files with 37 additions and 15 deletions

View File

@ -1,7 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import type { QueueItemSource } from '~/types' import type { QueueItemSource } from '~/types'
import { whenever, watchDebounced, useCurrentElement, useScrollLock, useFullscreen, useIdle, refAutoReset } from '@vueuse/core' import { whenever, watchDebounced, useCurrentElement, useScrollLock, useFullscreen, useIdle, refAutoReset, useStorage } from '@vueuse/core'
import { nextTick, ref, computed, watchEffect, onMounted } from 'vue' import { nextTick, ref, computed, watchEffect, onMounted } from 'vue'
import { useFocusTrap } from '@vueuse/integrations/useFocusTrap' import { useFocusTrap } from '@vueuse/integrations/useFocusTrap'
import { useGettext } from 'vue3-gettext' import { useGettext } from 'vue3-gettext'
@ -169,7 +169,7 @@ enum CoverType {
MILK_DROP MILK_DROP
} }
const coverType = ref(CoverType.COVER_ART) const coverType = useStorage('cover-type', CoverType.COVER_ART)
</script> </script>
<template> <template>

View File

@ -1,15 +1,20 @@
<script setup lang="ts"> <script setup lang="ts">
import { useMilkDrop } from '~/composables/audio/visualizer' import { useMilkDrop } from '~/composables/audio/visualizer'
import { onScopeDispose, ref } from 'vue' import { onScopeDispose, ref, watch } from 'vue'
import { useRafFn } from '@vueuse/core' import { useRafFn } from '@vueuse/core'
const milkdrop = ref() const milkdrop = ref()
const canvas = ref() const canvas = ref()
const { visualizer, loadRandomPreset, render } = useMilkDrop(canvas) const { visualizer, loadRandomPreset, render, isVisible } = useMilkDrop(canvas)
const { pause } = useRafFn(render) const { resume, pause } = useRafFn(render)
watch(isVisible, (visible) => visible
? resume()
: pause()
)
onScopeDispose(() => { onScopeDispose(() => {
pause() pause()

View File

@ -1,8 +1,8 @@
import type { Ref } from 'vue' import type { Ref } from 'vue'
import { AUDIO_CONTEXT, GAIN_NODE } from './audio-api' import { AUDIO_CONTEXT, GAIN_NODE } from './audio-api'
import { useResizeObserver } from '@vueuse/core' import { useResizeObserver, useStorage } from '@vueuse/core'
import { ref, markRaw } from 'vue' import { watchEffect, ref, markRaw } from 'vue'
// @ts-expect-error butterchurn has no typings // @ts-expect-error butterchurn has no typings
import butterchurnPresets from 'butterchurn-presets' import butterchurnPresets from 'butterchurn-presets'
@ -11,14 +11,26 @@ import butterchurnPresets from 'butterchurn-presets'
import butterchurn from 'butterchurn' import butterchurn from 'butterchurn'
export const useMilkDrop = (canvas: Ref<HTMLCanvasElement>) => { export const useMilkDrop = (canvas: Ref<HTMLCanvasElement>) => {
const presets = Object.entries(butterchurnPresets) const presets = Object.keys(butterchurnPresets)
const visualizer = ref() const visualizer = ref()
const loadRandomPreset = (blendTime = 1) => { const getRandomPreset = () => {
const index = (presets.length * Math.random()) | 0 const index = (presets.length * Math.random()) | 0
const [name, preset] = presets[index] return presets[index]
}
const presetName = useStorage<string | undefined>('milk-drop:preset', undefined)
watchEffect(() => {
const name = presetName.value
if (name === undefined) return
console.log(`Switching to preset: '${name}'`) console.log(`Switching to preset: '${name}'`)
visualizer.value.loadPreset(preset, blendTime) visualizer.value?.loadPreset(butterchurnPresets[name], 1)
})
const loadRandomPreset = () => {
const name = getRandomPreset()
presetName.value = name
} }
const initialize = (canvas: HTMLCanvasElement, width: number, height: number) => { const initialize = (canvas: HTMLCanvasElement, width: number, height: number) => {
@ -27,17 +39,21 @@ export const useMilkDrop = (canvas: Ref<HTMLCanvasElement>) => {
height height
})) }))
loadRandomPreset(0) if (presetName.value === undefined) {
presetName.value = getRandomPreset()
}
visualizer.value.connectAudio(GAIN_NODE) visualizer.value.connectAudio(GAIN_NODE)
visualizer.value.setInternalMeshSize(128, 96) visualizer.value.setInternalMeshSize(128, 96)
} }
const isVisible = ref(false)
useResizeObserver(canvas, ([entry]) => { useResizeObserver(canvas, ([entry]) => {
const { width, height } = entry.contentRect const { width, height } = entry.contentRect
console.log(width, height)
canvas.value.width = width canvas.value.width = width
canvas.value.height = height canvas.value.height = height
isVisible.value = !!(width * height)
if (visualizer.value === undefined) { if (visualizer.value === undefined) {
initialize(entry.target as HTMLCanvasElement, width, height) initialize(entry.target as HTMLCanvasElement, width, height)
@ -52,13 +68,14 @@ export const useMilkDrop = (canvas: Ref<HTMLCanvasElement>) => {
visualizer.value?.render() visualizer.value?.render()
} catch (error) { } catch (error) {
console.error(error) console.error(error)
loadRandomPreset(0) loadRandomPreset()
} }
} }
return { return {
visualizer, visualizer,
loadRandomPreset, loadRandomPreset,
render render,
isVisible
} }
} }