Pix主题 添加音乐 音频可视化

1️⃣ Eg

2️⃣ Pix 添加音乐配置

API:https://bohecat.com (感谢大佬提供的api 🤗

歌单列表id可以进入网易云web端歌单页获取

3️⃣ 编辑 - pixplayer.js

给 audio 标签添加 crossorigin 属性

/*
* pix主题音乐播放器 - before
*/

var rem=[];
rem.audio = $('<audio id="pix_player"></audio>');

var audiobox = $('<audio id="pix_player"></audio>');
var au = $('#pix_player');


/*
* pix主题音乐播放器 - after 
*/

var rem=[];
rem.audio = $('<audio id="pix_player" crossorigin="anonymous"></audio>');

var audiobox = $('<audio id="pix_player" crossorigin="anonymous"></audio>');
var au = $('#pix_player');

或许你想说

document.querySelector('#pix_player').setAttribute('crossorigin', 'anonymous')

但是很遗憾,这样不会生效 💦

4️⃣ JavaScript Source Code

<script type="text/javascript">
        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;
            const loadMediaEle = () => {
                media = document.querySelector('#pix_player');
                if (media != null) {
                    media.onplay = function () {
                        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()
        }

        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();
        }

        window.addEventListener("DOMContentLoaded", () => {
            musicInit()
        })
</script>
通过 Pix扩展设置 加入

打开 Pix主题设置 - 扩展设置 ,并将代码加入至 底部HTML代码 中

通过编辑 header.php 加入
<head>
    <meta charset="<?php bloginfo('charset'); ?>">
    <meta name="viewport"
          content="width=device-width,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0,user-scalable=no">
    <meta name="keywords" content="<?php getKeywords(); ?>">
    <meta name="description" content="<?php getDescription(); ?>">
    <title><?php gettitle(); ?></title>
    <link rel="profile" href="https://gmpg.org/xfn/11">
    <link rel="shortcut icon" href="<?php echo get_op('favicon'); ?>" title="Favicon">
    <?php wp_head(); ?>

    <!-- add start -->
    ...
    <!-- add end -->
</head>

5️⃣ 其中碰到的问题

MediaElementAudioSource outputs zeroes due to CORS access restrictions for xxx

跨域限制

即 audio 标签加入 crossorigin 属性所解决的问题

刚开始以为是 API 的原因,因为音频文件之类的都被重定向到了网易云音乐官方那边,猜想可能是网易那边做了跨域限制,于是就自己动手敲了一个代理服务,结果修改跨域配置后依然没有解决这个问题 🥲

然而网易云音乐官方有提供将播放器嵌入到其它页面的方案,所以大概是没做跨域限制的

至于使用 js 操作属性无效则是因为这个属性需要在设置 audio - src 之前就已经存在

消息盒子
# 您需要首次评论以获取消息 #
# 您需要首次评论以获取消息 #

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