给Hexo添加音乐播放器插件

看到大佬们的博客可以播放音乐,不得不说我🍋🍋🍋了。于是也来弄一个音乐播放器,真香~

Start

首先安装音乐插件hexo-tag-aplayer,APlayer是一款HTML5音乐播放器

1
npm install aplayer --save

在页面添加播放器,格式如下

1
{% aplayer title author url [picture_url, narrow, autoplay, width:xxx, lrc:xxx] %}
参数 说明
title 歌曲标题
author 歌曲作者
url 音乐文件URL地址
picture_url (可选)封面图片地址
narrow (可选)播放器袖珍风格
autoplay (可选)自动播放,移动端浏览器暂时不支持此功能
width (可选)播放器宽度 (默认: 100%)
lrc (可选)歌词文件 URL 地址

单曲实例

单曲具体代码
1
2
3
4
5
6
7
8
{% aplayer 
"光るなら"
"Goose house"
"https://cn-south-17-aplayer-46154810.oss.dogecdn.com/hikarunara.mp3"
"https://cn-south-17-aplayer-46154810.oss.dogecdn.com/hikarunara.jpg"
"lrc:https://cn-south-17-aplayer-46154810.oss.dogecdn.com/hikarunara.lrc"
"width:100%"
%}

歌曲文件,歌曲封面都可以引用本地文件,但是本地lrc歌词引用总是报错,用在线地址的就可以。引用本地文件还有一个问题,播放器的歌曲播放时间与总时常不能显示。所以最好都用外链。

歌单实例

歌单格式及具体例子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
{% aplayerlist %}
{
"narrow": false,
"autoplay": false,
"mode": "random",//(可选)'random', 'single' (单曲播放), 'circulation' (循环播放), 'order' (列表播放), 默认:'circulation'
"showlrc": 3,
"mutex": true,
"theme": "#e6d0b2",
"preload": "metadata",
"listmaxheight": "513px",
"music": [
{
"title": "前前前世",
"author": "RADWIMPS",
"url": "https://cn-south-17-aplayer-46154810.oss.dogecdn.com/yourname.mp3",
"pic": "https://cn-south-17-aplayer-46154810.oss.dogecdn.com/yourname.jpg",
"lrc": "https://cn-south-17-aplayer-46154810.oss.dogecdn.com/yourname.lrc"
},
{
"title": "光るなら",
"author": "Goose house",
"url": "https://cn-south-17-aplayer-46154810.oss.dogecdn.com/hikarunara.mp3",
"pic": "https://cn-south-17-aplayer-46154810.oss.dogecdn.com/hikarunara.jpg",
"lrc": "https://cn-south-17-aplayer-46154810.oss.dogecdn.com/hikarunara.lrc"
}
]
}
{% endaplayerlist %}

MetingJS支持

MetingJS是基于Meting API的APlayer衍生播放器

通过引入MetingJS,播放器将支持QQ音乐、网易云音乐、虾米、酷狗、百度等平台的音乐播放。
这种方式比较方便添加在线音乐播放列表。引入需要在Hexo的配置文件_config.yml中设置

_config.yml
1
2
3
aplayer:
meting: true # MetingJS 支持
asset_inject: true # 自动插入Aplayer.js与Meting.js资源脚本(默认开启)

设置后页面在初始化播放器时会引入1.2.0版本的Meting.min.js文件
注意不是在主题配置文件_config.yml设置,设置后要重启hexo服务才能生效

Meting的格式

1
{% meting "id" "server" "type"%}
选项 默认值 描述
id 必须值 歌曲 id / 播放列表 id / 相册 id / 搜索关键字
server 必须值 音乐平台: netease, tencent, kugou, xiami, baidu
type 必须值 song, playlist, album, search, artist
fixed false 开启固定模式
mini false 开启迷你模式
loop all 列表循环模式:all, one,none
order list 列表播放模式: list, random
volume 0.7 播放器音量
lrctype 0 歌词格式类型
listfolded false 指定音乐播放列表是否折叠
storagename metingjs LocalStorage 中存储播放器设定的键名
autoplay true 自动播放,移动端浏览器暂时不支持此功能
mutex true 该选项开启时,如果同页面有其他 aplayer 播放,该播放器会暂停
listmaxheight 340px 播放列表的最大长度
preload auto 音乐文件预载入模式,可选项: none, metadata, auto
theme #ad7a86 播放器风格色彩设置

MetingJS单曲

单曲Code
1
{% meting "1330348068" "netease" "song"  "theme: #1da496" %}

MetingJS歌单

播放列表Code
1
{% meting "387465322" "netease" "playlist" "" "mutex: false" "listmaxheight: 340px" "preload: none" "theme: #ad7a86" %}

播放器吸底模式

可以将播放器缩小在左下角,也称作“吸底模式”
如果在文章中将播放器的参数fixed激活,只会固定在文章页面中,要将其放在文章外,即博客的左下角,需要另外修改页面代码。
打开themes/next/layout/_layout.swig文件,在body标签里面的最后处加入aplyer的实例html代码

themes/next/layout/_layout.swig
1
2
3
4
5
6
7
8
9
10
11
<div class="aplayer" 
data-id="387465322"
data-server="netease"
data-type="playlist"
data-fixed="true"
data-autoplay="false"
data-order="list"
data-volume="0.5"
data-theme="#1da496"
data-preload="auto" >
</div>

在footer或者header引入依赖文件Aplayer.jsMeting.js,metingjs依赖aplayerjs,所以请注意顺序

themes/next/layout/_partials/footer.swig
1
2
3
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/aplayer@1.10.1/dist/APlayer.min.css">
<script src="https://cdn.jsdelivr.net/npm/aplayer@1.10.1/dist/APlayer.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/meting@1.2.0/dist/Meting.min.js"></script>

注意引入的metingjs版本得是1.2.0的,最新版本2.0.0与APlayer不兼容。看hexo-tag-aplayer的github仓库两年前更新后就没动了,只支持到metingjs的v1.2.0
hexo-tag-aplayer
metingjs文档

因为在主题文件中手动加入了依赖文件,所以可以在hexo配置文件中关闭插件的自动脚本插入功能:

_config.yml
1
2
3
aplayer:
meting: true
asset_inject: false # 关闭自动脚本插入

重启服务器可看到首页出现左下角的播放器了。

引入pjax实现全局播放

当进入其他页面时,吸底播放器会被打断。要实现音乐的不间断播放,也就是全局音乐效果,可以使用pjax。Next主题已经自带了MoOx/pjax,可手动开启。
在主题设置文件_config.yml中将pjax设置为true,并且找到下面一句,将里面的注释去掉,引入cdn资源。

1
# pjax: //cdn.jsdelivr.net/gh/theme-next/theme-next-pjax@0/pjax.min.js

这样跳转到其他页面就不会打断首页的播放器了。

进阶

引入pjax后会与不少功能冲突了,比如图片放大,文章页面里的aplayer无法初始化等
这是因为局部页面替换,里面的js没有执行,所以很多涉及到js的功能就异常了。
为解决文章页面的APlayer的初始化异常问题,因在进入有播放器页面的时候,此时正好pjax执行成功,可在其对应的监听事件里执行metingjs的初始化函数,这样页面的播放器就能实例化了。
从metingjs的1.2.0源码可以看到里面有loadMeting()的初始化函数。
所以在pjax的success监听事件里以及页面加载的时候都调用初始化函数。

1
2
3
4
5
6
7
document.addEventListener('pjax:success', function(){
loadMeting();
});

document.onload = function(){
loadMeting();
}

其他功能兼容pjax的解决方法跟这个大同小异,也是先封装在一个函数里再两边调用。

添加js后进入有播放器的页面,就可以看到初始化后的播放器了。但是又有新的问题,左下角的全局播放器会被中断。这是因为这个loadMeting()函数默认会重载页面上的所有播放器,左下角的全局播放器也会被影响到。

这问题现在MetingJS已经更新了解决代码github releases

当播放器的容器带有 no-destroy 类时该播放器不会被销毁与重载,适合不间断播放的全站播放器使用

所以在左下角吸底播放器标签代码中加入no-destroy类就可以保持不被销毁。

1
<div class="aplayer no-destroy" data-id="xxx"...></div>

注意:上面引入的是jsdelivr的1.2.0 Meting.min.js,里面并没有更新no-destroy这个功能的代码,可以将新源码新1.2.0源码保存在本地直接引用

themes/next/layout/_partials/footer.swig
1
2
3
<script src="https://cdn.jsdelivr.net/npm/meting@1.2.0/dist/Meting.min.js"></script>
<!--上面的依赖不能使用-->
<script src="/js/Meting.min.js"></script>

最后重启hexo服务

1
$ hexo clean && heax g && hexo s

就这?是的,就这样解决了

无关痛痒的异常

页面有播放器,可发现有这样的报错:Cannot read property 'classList' of undefined

这报错并不影响使用,那真就无视呗。抱歉,搞起~
点进list.js可看到异常的代码具体是

list.js
1
this.player.container.querySelectorAll('.aplayer-list li')[this.index].classList.add('aplayer-list-light');

这是要在播放列表中的歌曲之前加选中样式,但是找不到dom元素才报错。可是页面中元素是存在的,并不为null。

有大佬指出了具体原因issues

由于在pjax完成时Meting会调用APlayer的析构,其会取消异步请求,导致其绑定的switch函数被调用,switch函数在调用时会更新页面的元素,而pjax此时已经刷新了页面,故会抛出一个undefined的异常

并且提供解决思路:

1
2
// aplayer 是 new APlayer 返回的对象 
aplayer.list.index = undefined;

具体代码就要自己写了,其实不难。结合meting.js代码,可知道每个播放器对象都存在aplayers数组里,在Meting初始化之前将aplayer的属性改了就行

1
2
3
4
5
6
document.addEventListener('pjax:success', function () {
for(var i in aplayers){
aplayers[i].list.index = undefined;
}
loadMeting();
})

这样就会跳过switch函数,从而不会抛出异常了。

End

添加这个音乐播放器还是花了一些时间,对于没有前端基础知识的来说可能会有点吃力。特别是pjax部分,不懂的可以看看官方文档,会有帮助的。

参考

hexo-tag-aplayer中文说明文档
APlayer官方文档
为Hexo博客添加全局APlayer播放器
完善loadMeting()
MoOx/pjax官方文档
Hexo博客部署Pjax局部刷新
pjax导致无法初始化aplayer音乐播放器