generated from VLADIMIR/template_frontend
ups
This commit is contained in:
@@ -31,12 +31,7 @@ const binding = ref(false)
|
||||
const bindSuccess = ref(false)
|
||||
const introAudioElement = ref<HTMLAudioElement>()
|
||||
const conclusionVideoElement = ref<HTMLVideoElement>()
|
||||
const visualizerCanvas = ref<HTMLCanvasElement>()
|
||||
let appliedCommandVersion = 0
|
||||
let audioContext: AudioContext | undefined
|
||||
let analyser: AnalyserNode | undefined
|
||||
let audioSource: MediaElementAudioSourceNode | undefined
|
||||
let visualizerFrame = 0
|
||||
let pollTimer: number | null = null
|
||||
|
||||
const bindingFlow = computed(() => Boolean(route.query.screenId && route.query.accessToken))
|
||||
@@ -134,43 +129,10 @@ async function loadGames() {
|
||||
}
|
||||
}
|
||||
|
||||
function startVisualizer() {
|
||||
const audio = introAudioElement.value
|
||||
const canvas = visualizerCanvas.value
|
||||
if (!audio || !canvas || audioSource) return
|
||||
try {
|
||||
audioContext = new AudioContext()
|
||||
analyser = audioContext.createAnalyser()
|
||||
analyser.fftSize = 64
|
||||
audioSource = audioContext.createMediaElementSource(audio)
|
||||
audioSource.connect(analyser)
|
||||
analyser.connect(audioContext.destination)
|
||||
const data = new Uint8Array(analyser.frequencyBinCount)
|
||||
const draw = () => {
|
||||
if (!analyser || !visualizerCanvas.value) return
|
||||
const context = visualizerCanvas.value.getContext('2d')
|
||||
if (!context) return
|
||||
analyser.getByteFrequencyData(data)
|
||||
context.clearRect(0, 0, canvas.width, canvas.height)
|
||||
const barWidth = canvas.width / data.length
|
||||
data.forEach((value, index) => {
|
||||
const height = (value / 255) * canvas.height
|
||||
context.fillStyle = `hsl(${160 + index * 3} 70% 60%)`
|
||||
context.fillRect(index * barWidth, canvas.height - height, Math.max(2, barWidth - 1), height)
|
||||
})
|
||||
visualizerFrame = requestAnimationFrame(draw)
|
||||
}
|
||||
draw()
|
||||
} catch {
|
||||
// Браузер может запретить анализ MediaElement, воспроизведение при этом остаётся доступным.
|
||||
}
|
||||
}
|
||||
|
||||
watch(state, async (value) => {
|
||||
if (!value || !value.command || value.stateVersion === appliedCommandVersion) return
|
||||
appliedCommandVersion = value.stateVersion || 0
|
||||
await nextTick()
|
||||
startVisualizer()
|
||||
const media = screenMode.value === 'SCREEN_MODE_CONCLUSION' ? conclusionVideoElement.value : introAudioElement.value
|
||||
if (!media) return
|
||||
media.currentTime = (value.positionMs || 0) / 1000
|
||||
@@ -239,8 +201,6 @@ onMounted(async () => {
|
||||
onUnmounted(() => {
|
||||
if (pollTimer != null) window.clearInterval(pollTimer)
|
||||
if (resultsScrollTimer != null) window.clearInterval(resultsScrollTimer)
|
||||
cancelAnimationFrame(visualizerFrame)
|
||||
void audioContext?.close()
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -276,9 +236,6 @@ onUnmounted(() => {
|
||||
<div v-else class="screen-content" :style="screenBackground">
|
||||
<p v-if="mediaError" class="media-error">{{ mediaError }}</p>
|
||||
<div v-if="screenMode === 'SCREEN_MODE_INTRO' && state.introAudio" class="screen-media">
|
||||
<div class="sound-track">
|
||||
<canvas ref="visualizerCanvas" width="640" height="120" />
|
||||
</div>
|
||||
<audio ref="introAudioElement" :src="introAudio" :muted="!state.soundEnabled" autoplay controls />
|
||||
</div>
|
||||
<div v-else-if="screenMode === 'SCREEN_MODE_CONCLUSION' && state.conclusionVideo" class="screen-media">
|
||||
@@ -460,17 +417,5 @@ onUnmounted(() => {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.sound-track {
|
||||
margin: 0 auto 20px;
|
||||
max-width: 720px;
|
||||
}
|
||||
|
||||
.sound-track canvas {
|
||||
background: #161616;
|
||||
display: block;
|
||||
height: 120px;
|
||||
max-width: 100%;
|
||||
width: 640px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user