Pix 添加 音频可视化 + 歌词 🎵

1. Eg

mKaZbElxD6KFefKskbh8
d5vPXoeN4htspRX9euXx

2. JavaScript Source Code

Pix 添加 音频可视化 🌈

继上一篇文章,替换 js 代码即可

<script type="text/javascript">
        const getColor = () => {
            if (document.body.classList.value.indexOf('dark') > -1) return "#8c92b3"
            else return "#5f936e"
        }

        const drawAudioLine = (ctx, x, y, w, h, color) => {
            // 绘制方形
            ctx.save()
            ctx.translate(x, y)
            ctx.scale(1, -1)
            ctx.fillStyle = color;
            ctx.beginPath();
            ctx.fillRect(0, 0, w, h)
            ctx.closePath();
            ctx.fill();
            ctx.restore();

            // 绘制顶部圆
            ctx.save()
            ctx.translate(x, y - h)
            ctx.scale(1, -1)
            ctx.fillStyle = color;
            ctx.beginPath();
            ctx.arc((w / 2), 0, (w / 2), 0, 360 * Math.PI / 180, false);
            ctx.closePath();
            ctx.fill();
            ctx.restore();

            // 绘制底部圆
            ctx.save()
            ctx.translate(x, y)
            ctx.scale(1, -1)
            ctx.fillStyle = color;
            ctx.beginPath();
            ctx.arc((w / 2), 0, (w / 2), 0, 360 * Math.PI / 180, false);
            ctx.closePath();
            ctx.fill();
            ctx.restore();
        }

        const musicInit = async () => {
            let audioCanvasElement = document.createElement('canvas'), canvasW = 200;
            document.body.append(audioCanvasElement)
            audioCanvasElement.id = 'audio_canvas';
            audioCanvasElement.style.height = '150px';
            audioCanvasElement.style.width = canvasW + 'px';
            audioCanvasElement.style.position = 'fixed';
            audioCanvasElement.style.bottom = '0';
            audioCanvasElement.style.zIndex = '999';

            let sidebarRight = document.querySelector('.sidebar_right');
            let beginX = sidebarRight.getBoundingClientRect().x;
            beginX = beginX + ((sidebarRight.clientWidth + canvasW) / 2) - canvasW;
            audioCanvasElement.style.left = beginX + 'px';

            audioCanvasElement.width = canvasW;
            audioCanvasElement.height = '150';

            let audioCanvasCtx = audioCanvasElement.getContext('2d');
            audioCanvasCtx.save();
            let beginPointY = audioCanvasElement.height, beginPointX = 0;

            let media = null, audioCtx = null, analyser = null, sourceElement = null;
            generateLrcElement()
            const loadMediaEle = () => {
                media = document.querySelector('#pix_player');
                if (media != null) {
                    media.ontimeupdate = async (e) => {
                        await lyricsLoad(media)
                    }
                    media.onplay = async () => {
                        // get lyrics
                        lrcOriginal = await $.get('https://bohecat.com/musicapi/?type=lrc&id=' + media.getAttribute('src').split('id=')[1] + '&source=netease');

                        if (!analyser) {
                            audioCtx = new window.AudioContext();
                            analyser = audioCtx.createAnalyser();
                            analyser.fftSize = 512;
                            analyser.connect(audioCtx.destination);
                            sourceElement = audioCtx.createMediaElementSource(media);
                            sourceElement.connect(analyser);
                        }

                        let bufferLength = analyser.frequencyBinCount;
                        let dataArray = new Uint8Array(bufferLength);
                        (function task() {
                            window.requestAnimationFrame(task);
                            analyser.getByteFrequencyData(dataArray);

                            audioCanvasCtx.clearRect(0, 0, audioCanvasElement.width, audioCanvasElement.height);

                            let n = 30, aw = canvasW / n, w = aw - 2, easing = .8, lastH = 0,
                                add = Math.floor(dataArray.length / n), index = 0;
                            for (let i = 0; i < n; i++) {
                                let barHeight = dataArray[index];
                                let h = (barHeight / 3 - lastH) * easing
                                h += lastH
                                drawAudioLine(audioCanvasCtx, beginPointX + (i * aw) + (aw / 2 - w / 2), beginPointY, 4, h, getColor());
                                index += Math.floor(add / 2);
                            }
                        })()
                    }
                } else {
                    setTimeout(() => {
                        loadMediaEle()
                    }, 50)
                }
            }
            loadMediaEle()
        }

        /* music lyrics */
        let lrcDom, lastIndex = -1, lrcArr, lrcContainerW = 200, lrcOriginal

        const generateLrcElement = () => {
            let lrcContainer = document.createElement('div')
            lrcContainer.id = 'music-lyrics'
            lrcContainer.style.position = 'fixed'

            let audioCanvas = document.querySelector('#audio_canvas')
            // lrcContainer.style.bottom = audioCanvas.clientHeight + 'px'
            lrcContainer.style.bottom = '110px'
            lrcContainer.style.left = audioCanvas.getBoundingClientRect().x + 'px'
            lrcContainer.style.width = lrcContainerW + 'px'
            lrcContainer.style.height = 100 + 'px'
            lrcContainer.style.zIndex = '999'
            document.body.append(lrcContainer)
        }

        const lyricsLoad = async (media) => {
            const handle = {
                lyricsDomHandle: (data) => {
                    if (lrcDom.children.length >= 1) {
                        lrcDom.removeChild(lrcDom.childNodes[0])
                    }
                    handle.lyricsItemAdd(data.v, data.i)
                },
                lyricsItemAdd: (lrc, index) => {
                    const genChild = (text) => {
                        let childEl = document.createElement('div')
                        childEl.innerHTML = text
                        return childEl
                    }
                    let el = document.createElement('div')
                    el.id = 'lrc_id_' + index
                    el.classList.add('lrc-in')
                    lrc.forEach(v => {
                        el.appendChild(genChild(v || '...'))
                    })
                    lrcDom.appendChild(el)
                },
                lyricsByTime: (time) => {
                    let arr = [], obj = {}, res = []
                    for (let j = 0; j < lrcArr.length; j++) {
                        if (lrcArr[j][0] <= time) {
                            obj.i = j
                            arr.push(lrcArr[j])
                        }
                    }
                    let last = arr[arr.length - 1] ? arr[arr.length - 1][0] : '-1'
                    arr.forEach(v => {
                        if (v[0] == last) {
                            res.push(v[1])
                        }
                    })
                    obj.v = res
                    return obj
                }
            }

            lrcDom = document.querySelector('#music-lyrics')
            if (lrcOriginal) {
                lrcArr = lyricsOriginalHandle(lrcOriginal)
                let data = handle.lyricsByTime(media.currentTime)
                if (lastIndex != data.i) {
                    handle.lyricsDomHandle(data)
                    lastIndex = data.i
                }
            }
        }

        const lyricsOriginalHandle = (original) => {
            let res = original.split('[')
            let lrcArr = []
            for (let i = 0; i < res.length; i++) {
                if (res[i]) {
                    let data = res[i].split(']')
                    data[1] = data[1].replace(/^\s+/, '').replace(/\s+$/, '')
                    let timeArr = data[0].split(':')
                    let min = Number(timeArr[0]) * 60, sec = Number(timeArr[1])
                    data[0] = min + sec
                    lrcArr.push(data)
                }
            }
            // 处理前奏过长且歌词源数据的开始时间不为0
            if (lrcArr[0][0] > 0) {
                lrcArr.unshift([0, ''])
            }
            return lrcArr
        }

        window.addEventListener("DOMContentLoaded", () => {
            musicInit()
        })
    </script>
消息盒子
# 您需要首次评论以获取消息 #
# 您需要首次评论以获取消息 #

只显示最新10条未读和已读信息