MENU

任意站点引入 APlayer 和 Meting 的简单方法

2020 年 02 月 11 日 • 阅读: 5418 • 博客

关于 音视频播放,之前介绍过 DPlayerYoduPlayer,今天介绍下 APlayerMeting,可播放 网易云QQ 音乐酷狗虾米百度 以及 自定义的 单曲和歌单,按需加载 JS,不依赖插件和服务器计算存储,任意站点都可使用。

引入 JS

对于 本主题,依次进入 控制台 - 外观 - 设置外观 - 主题自定义扩展,将代码加入到 自定义 HTML 元素拓展 - 标签: head 头部 (meta 元素后)。其他主题,加入到主题对应的 header.php 中的 </head> 标签前。

Almost JavaScript Code

<script>
    // APlayer API
    document.addEventListener('DOMContentLoaded', initAplayer);
    window.aplayers = window.aplayers || [];
    function initAplayer(option) {
        const common = {
            loadResource: function (id, resource, type) {
                return new Promise(function (resolve, reject) {
                    let loaded = document.head.querySelector('#' + id);
                    if (loaded) {
                        resolve('success: ' + resource);
                        return;
                    }
                    const element = document.createElement(type);
                    element.onload = element.onreadystatechange = () => {
                        if (!loaded && (!element.readyState || /loaded|complete/.test(element.readyState))) {
                            element.onload = element.onreadystatechange = null;
                            loaded = true;
                            resolve('success: ' + resource);
                        }
                    }
                    element.onerror = function () {
                        reject(Error(resource + ' load error!'));
                    };
                    if (type === 'link') {
                        element.rel = 'stylesheet';
                        element.href = resource;
                    } else {
                        element.src = resource;
                    }
                    element.id = id;
                    document.getElementsByTagName('head')[0].appendChild(element);
                });
            },
            loadResources: function (callback) {
                const loadResource = this.loadResource;
                const pt = '//s0.pstatp.com/cdn/expire-1-M/';
                const jd = '//cdn.jsdelivr.net/npm/';
                const resources = [
                    pt + 'aplayer/1.10.1/APlayer.min.css',
                    pt + 'aplayer/1.10.1/APlayer.min.js',
                    jd + 'meting@2/dist/Meting.min.js'
                ];
                const loadPromises = [];
                resources.forEach(resource => {
                    loadPromises.push(loadResource(btoa(resource).replace(/[=+\/]/g, ''), resource,
                        ({
                            'css': 'link',
                            'js': 'script'
                        })[resource.split('.').pop()]
                    ));
                });
                Promise.all(loadPromises).then(
                    function () {
                        if (typeof callback !== 'function') return;
                        let flag = false;
                        const waitAM = setInterval(() => {
                            if (!flag
                                && typeof APlayer === 'function'
                                && typeof MetingJSElement === 'function') {
                                flag = true;
                                callback();
                                clearInterval(waitAM);
                            }
                        }, 100);
                    }
                );
            },
            createAplayers: function (sources) {
                for (let i = 0; i < sources.length; i++) {
                    const child = document.createElement('div');
                    sources[i].parentNode.insertBefore(child, sources[i]);
                    sources[i].style.display = 'none';
                    const songsTag = sources[i].querySelectorAll('s');
                    const songs = [];
                    songsTag.forEach(songTag => {
                        const song = {};
                        for (let i = 0; i < songTag.attributes.length; i++) {
                            song[songTag.attributes[i].name] = songTag.attributes[i].value;
                        }
                        songs.push(song);
                    });
                    const options = { container: child, preload: 'none', autoplay: false, audio: songs };
                    const optionMap = sources[i].attributes;
                    for (let i = 0; i < optionMap.length; i++) {
                        options[optionMap[i].name] = optionMap[i].value;
                    }
                    this.loadResources(() => window.aplayers.push(new APlayer(options)));
                }
            }
        };

        if (option == 'manual') return new Promise((resolve, reject) => {
            common.loadResources(() => resolve('success'));
        });

        const aps = document.querySelectorAll('ap');
        if (aps.length !== 0) common.createAplayers(aps);

        const mts = document.querySelectorAll('meting-js');
        if (!window.refreshing && mts.length !== 0) common.loadResources(
            function () {
                mts.forEach(mt => {
                    if (!mt.aplayer) {
                        const html = mt.outerHTML;
                        mt.aplayer = { destroy: new Function(), list: { index: undefined } };
                        mt.outerHTML = '\n' + html;
                    }
                });
                document.querySelectorAll('meting-js').forEach(mt => {
                    let flag = false;
                    const waitMT = setInterval(() => {
                        if (!flag && mt.aplayer) {
                            flag = true;
                            window.aplayers.push(mt.aplayer);
                            console.log('replaced unloaded aplayer.')
                            clearInterval(waitMT);
                        }
                    }, 300);
                });
            }
        );
    }
</script>

<script>
    // PJAX 相关 BUG
    document.addEventListener('DOMContentLoaded', function () {
        let flag = false;
        window.needReloadUrls = window.needReloadUrls || new Set();
        const jqueryWaitor = setInterval(() => {
            if (!flag && jQuery) {
                flag = true;
                $(document).on('pjax:start', function () {
                    if (!window.refreshing || !window.pjaxStarted) {
                        window.pjaxStarted = true;
                        console.log('pjax:start');
                        window.aplayers.forEach(ap => {
                            ap.list.index = undefined;
                            ap.destroy();
                        });
                        window.aplayers = [];
                        setTimeout(() => window.pjaxStarted = false, 2000);
                    }
                });
                $(document).on('pjax:end', function () {
                    if (document.querySelector('meting-js')
                        || document.querySelector('.collapse-block')
                        || document.querySelector('#toggle-menu-tree')
                        || document.querySelectorAll('.content-tab-title').length > 1
                    ) {
                        if (!window.needReloadUrls.has(location.href)) {
                            window.needReloadUrls.add(location.href);
                            console.log('captured a neededReloadUrl.');
                        }
                    }
                });
                $(document).on('pjax:popstate', function (event) {
                    if (event.state && window.needReloadUrls.has(event.state.url) && !window.refreshing) {
                        window.refreshing = true;
                        console.log('back-forward handler.');
                        $.pjax.reload({
                            url: location.href,
                            container: '#body',
                            fragment: '#body',
                            scrollTo: false,
                            timeout: 8000
                        });
                        setTimeout(() => window.refreshing = false, 2000);
                    }
                });
                clearInterval(jqueryWaitor);
            }
        }, 500);
    });
</script>

如果你开启了 PJAX,可能需要单独加入回调函数。对于本主题,依次进入 控制台 - 外观 - 设置外观 - PJAX(BETA) - PJAX RELOAD,将 initAplayer(); 添加进入即可。

演示效果

在文章所需位置以 HTML 形式插入代码,即可添加播放器。

!!!
<!-- 引入方式 -->
<meting-js auto="https://music.163.com/#/playlist?id=110459831"></meting-js>
!!!
!!!
<!-- 引入方式 -->
<meting-js auto="https://y.qq.com/n/yqq/playlist/7355087593.html"></meting-js>
!!!
!!!
<!-- 标签引入 -->
<ap>
<s
    name="rainymood"
    artist="rainymood"
    url="https://rainymood.com/audio1110/0.m4a"
    cover="https://rainymood.com/i/badge.jpg">
</s>
</ap>
!!!

!!!
<!-- 或编程引入 -->
<div id="ap"></div>
<script>
    initAplayer('manual').then(() => {
        window.aplayers.push(new APlayer({
            container: document.querySelector('#ap'), preload: 'none', autoplay: false, audio: [
                {
                    name="rainymood",
                    artist="rainymood",
                    url="https://rainymood.com/audio1110/0.m4a",
                    cover="https://rainymood.com/i/badge.jpg"
                }
            ]
        }));
    });
</script>
!!!

TG 大佬群 QQ 大佬群 QQ 追番群

最后编辑于: 2020 年 02 月 21 日
返回文章列表 文章二维码
本页链接的二维码
打赏二维码
添加新评论

已有 25 条评论
  1. 小明同学 小明同学     Windows 10 /    Google Chrome

    大佬,网易云和QQ咋都挂了,显示不了了!!!~

    1. LOGI LOGI     Windows 10 /    Google Chrome

      @小明同学自建下API吧,可能官方用的人太多了
      https://github.com/metowolf/MetingJS#advanced

    2. 小明同学 小明同学     Windows 10 /    Google Chrome

      @LOGI小白表示不会,请问有没有详细步骤可以学习

    3. LOGI LOGI     Windows 10 /    Google Chrome

      @小明同学可以加群

  2. 月下读心 月下读心     iPhone /    Safari

    大佬,网易和QQ都失效了

    1. LOGI LOGI     Windows 10 /    Google Chrome

      @月下读心示例正常@(呵呵)

    2. 月下读心 月下读心     iPhone /    Safari

      @LOGI现在看正常了,尴尬

  3. 初夏阳光 初夏阳光     Windows 10 /    Google Chrome

    我吐了,我写了一大篇,然后超出200字符限制了,删了又删才发出去了。。
    链接:https://github.com/MoePlayer/hexo-tag-aplayer/blob/master/docs/README-zh_cn.md#pjax-%E5%85%BC%E5%AE%B9

    1. LOGI LOGI     Windows 10 /    Google Chrome

      @初夏阳光后台看到我感动哭了,这个方法我看了,后来发现本题本身也有 bug,所以等待主题作者进度了

    2. LOGI LOGI     Windows 10 /    Google Chrome

      @初夏阳光当初写这段代码原因之一是 Aplayer 插件和我写的 Dplayer 冲突,其次是想着检测到 meting-js 标签再加载 js css,大多数页面就可以少发几个请求了

  4. 初夏阳光 初夏阳光     Windows 10 /    Google Chrome

    关于Pjax我今天找到了一个解决方案,Pjax开始时清理APlayer全局实例。虽然我看你那个 135 行好像也是清除全局实例。但你的 Pjax 回退到 Aplayer 的时候 Meting.js 报错 Cannot read property 'destroy' of undefined

    1. LOGI LOGI     Windows 10 /    Google Chrome

      @初夏阳光看你评论好多遍,我都心疼@(笑尿),是触发了哪些规则呢

    2. 初夏阳光 初夏阳光     Windows 10 /    Google Chrome

      @LOGI一直都是超过了200个字符限制。还说我不认真评论找不到女朋友。www

    3. LOGI LOGI     Windows 10 /    Google Chrome

      @初夏阳光之前被刷评搞得很烦,所以不得已

    4. 初夏阳光 初夏阳光     Windows 10 /    Google Chrome

      @LOGI我的垃圾评论也有一些,开了不包含中文的全拦截。现在偶尔有几条我都是手动清的,毕竟有的时候冷冷清清看一看垃圾评论也可消遣一下

  5. 小童 小童     Windows 10 /    Google Chrome

    发现了一个关于播放器显示的bug,不知道是主题问题还是啥问题,而且大佬你和我博客都存在。
    在有加载播放器的页面的时候,点击任意按钮或者离开当前页面进入下一页面之后,使用浏览器的返回,返回到有加载播放器的页面的时候,会出现播放器重叠情况,手机端电脑端谷歌qq浏览器经过尝试都会出现。是和hran的主题存在冲突嘛#(期待)

    1. LOGI LOGI     Windows 10 /    Google Chrome

      @小童是 meting-js 的 bug,稍后解决

    2. LOGI LOGI     Windows 10 /    Google Chrome

      @LOGI我更新了,有问题再反馈,pjax 会产生很多错误,不仅仅是播放器,主题本身也有 bug,比如折叠框和多标签按钮在返回前进后都无法点击,该问题我已经告诉主题作者了

    3. 小童 小童     Windows 10 /    Google Chrome

      @LOGI咋整的呀@(小乖)我看你已经好了

    4. LOGI LOGI     Windows 10 /    Google Chrome

      @小童替换下代码

    5. 小童 小童     Windows 10 /    Google Chrome

      @LOGI谢谢大佬@(乖)

  6. 于长野 于长野     Windows 10 /    Google Chrome

    #(献花)

  7. 初夏阳光 初夏阳光     Windows 10 /    Google Chrome

    诶,整的好!@(真棒)

  8. Xin Xin     Windows 10 /    Google Chrome

    很赞,连插件都省了@(呵呵)

    1. LOGI LOGI     Windows 10 /    Google Chrome

      @Xin之前的有点问题,如果在用就更新下代码@(哈哈)

0:00