播放详情页新增音频可视化功能

This commit is contained in:
lyswhut
2021-12-24 17:39:50 +08:00
parent dcfe055461
commit c2d6737796
11 changed files with 171 additions and 3 deletions
@@ -0,0 +1,132 @@
<template>
<div :class="$style.content">
<canvas :class="$style.canvas" ref="dom_canvas"></canvas>
</div>
</template>
<script>
import { ref, onBeforeUnmount, onMounted, useRefGetter, watch } from '@renderer/utils/vueTools'
import { getAnalyser } from '@renderer/plugins/player'
import { isPlay } from '@renderer/core/share/player'
import { player as eventPlayerNames } from '@renderer/event/names'
const themes = {
green: 'rgba(77,175,124,.1)',
blue: 'rgba(52,152,219,.1)',
yellow: 'rgba(233,212,96,.16)',
orange: 'rgba(245,171,53,.1)',
red: 'rgba(214,69,65,.08)',
pink: 'rgba(241,130,141,.1)',
purple: 'rgba(155,89,182,.1)',
grey: 'rgba(108,122,137,.1)',
ming: 'rgba(51,110,123,.1)',
blue2: 'rgba(79,98,208,.1)',
black: 'rgba(39,39,39,.26)',
mid_autumn: 'rgba(74,55,82,.05)',
naruto: 'rgba(87,144,167,.1)',
happy_new_year: 'rgba(252,57,57,.1)',
}
export default {
setup() {
const dom_canvas = ref(null)
const analyser = getAnalyser()
let ctx
let bufferLength
let dataArray
let WIDTH
let HEIGHT
let barWidth
let barHeight
let x = 0
let isPlaying = false
const theme = useRefGetter('theme')
// const setting = useRefGetter('setting')
let themeColor = themes[theme.value || 'green']
watch(theme, theme => {
themeColor = themes[theme || 'green']
})
// https://codepen.io/nfj525/pen/rVBaab
const renderFrame = () => {
if (isPlaying) window.requestAnimationFrame(renderFrame)
x = 0
analyser.getByteFrequencyData(dataArray)
ctx.clearRect(0, 0, WIDTH, HEIGHT)
// ctx.fillRect(0, 0, WIDTH, HEIGHT)
for (let i = 0; i < bufferLength; i++) {
barHeight = dataArray[i]
// let r = barHeight + (25 * (i / bufferLength))
// let g = 250 * (i / bufferLength)
// let b = 50
// ctx.fillStyle = 'rgb(' + r + ',' + g + ',' + b + ')'
ctx.fillStyle = themeColor
ctx.fillRect(x, HEIGHT - barHeight, barWidth, barHeight)
x += barWidth
}
}
const handlePlay = () => {
isPlaying = true
analyser.fftSize = 256
bufferLength = analyser.frequencyBinCount
// console.log(bufferLength)
barWidth = (WIDTH / bufferLength) * 2.5
dataArray = new Uint8Array(bufferLength)
renderFrame()
}
const handlePause = () => {
isPlaying = false
}
window.eventHub.on(eventPlayerNames.play, handlePlay)
window.eventHub.on(eventPlayerNames.pause, handlePause)
window.eventHub.on(eventPlayerNames.error, handlePause)
onBeforeUnmount(() => {
handlePause()
window.eventHub.off(eventPlayerNames.play, handlePlay)
window.eventHub.off(eventPlayerNames.pause, handlePause)
window.eventHub.off(eventPlayerNames.error, handlePause)
})
onMounted(() => {
const canvas = dom_canvas.value
ctx = canvas.getContext('2d')
canvas.width = canvas.clientWidth
canvas.height = canvas.clientHeight
WIDTH = canvas.width
HEIGHT = canvas.height
if (isPlay.value) handlePlay()
})
return {
dom_canvas,
}
},
}
</script>
<style lang="less" module>
.content {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 100;
}
.canvas {
width: 100%;
height: 100%;
// opacity: 0.1;
}
</style>
+4
View File
@@ -222,5 +222,9 @@ svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/19
// 0 0 24 24
path(fill='currentColor', d='M21,6V8H3V6H21M3,18H12V16H3V18M3,13H21V11H3V13Z')
g#icon-audio-wave(fill='currentColor')
// 0 0 24 24
path(fill='currentColor', d='M22 12L20 13L19 14L18 13L17 16L16 13L15 21L14 13L13 15L12 13L11 17L10 13L9 22L8 13L7 19L6 13L5 14L4 13L2 12L4 11L5 10L6 11L7 5L8 11L9 2L10 11L11 7L12 11L13 9L14 11L15 3L16 11L17 8L18 11L19 10L20 11L22 12Z')
</template>
@@ -6,6 +6,9 @@ div(:class="$style.footerLeftControlBtns")
use(xlink:href='#icon-desktop-lyric-on')
svg(v-show="!setting.desktopLyric.enable" version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' height='125%' viewBox='0 0 512 512' space='preserve')
use(xlink:href='#icon-desktop-lyric-off')
div(:class="[$style.footerLeftControlBtn, { [$style.active]: setting.player.audioVisualization }]" @click="toggleAudioVisualization" :tips="$t('audio_visualization')")
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' width='95%' viewBox='0 0 24 24' space='preserve')
use(xlink:href='#icon-audio-wave')
div(:class="[$style.footerLeftControlBtn, { [$style.active]: isShowLrcSelectContent }]" @click="toggleVisibleLrc" :tips="$t('lyric__select')")
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' width='95%' viewBox='0 0 24 24' space='preserve')
use(xlink:href='#icon-text')
@@ -31,7 +34,7 @@ div(:class="$style.footerLeftControlBtns")
</template>
<script>
import { useI18n, useRefGetter, ref } from '@renderer/utils/vueTools'
import { useI18n, useRefGetter, ref, useCommit } from '@renderer/utils/vueTools'
import {
isShowLrcSelectContent,
@@ -48,6 +51,7 @@ export default {
setup() {
const { t } = useI18n()
const setting = useRefGetter('setting')
const setAudioVisualization = useCommit('setAudioVisualization')
const toggleVisibleLrc = () => {
setShowPlayLrcSelectContentLrc(!isShowLrcSelectContent.value)
@@ -68,6 +72,10 @@ export default {
const isShowAddMusicTo = ref(false)
const toggleAudioVisualization = () => {
setAudioVisualization(!setting.value.player.audioVisualization)
}
return {
setting,
isShowLrcSelectContent,
@@ -79,6 +87,7 @@ export default {
toggleDesktopLyricBtnTitle,
toggleDesktopLyric,
toggleLockDesktopLyric,
toggleAudioVisualization,
isShowAddMusicTo,
musicInfoItem,
}
@@ -32,6 +32,8 @@ transition(enter-active-class="animated lightSpeedIn" leave-active-class="animat
music-comment(:class="$style.comment" :musicInfo="musicInfoItem" :show="isShowPlayComment" @close="hideComment" v-if="visibled")
transition(enter-active-class="animated fadeIn" leave-active-class="animated fadeOut")
play-bar(v-if="visibled")
transition(enter-active-class="animated-slow fadeIn" leave-active-class="animated-slow fadeOut")
common-audio-visualizer(v-if="setting.player.audioVisualization && visibled")
</template>