foreword
If you want to add APlayer to you site, just two steps.
- load APlayer, from cdn or local.
- init APlayer.
However, if you have customized requirements, more things need to be done.
For example, I want a fixed APlayer without lyrics on some pages of my site, while a normal APlayer with lyrics embedded in custom area on the /music page. Because I want to see lyrics at the /music page while not at other page.
In order to control how APlayer is displayed in different page, I add aplayer configuration to _config.yml. Here are what I have done.
add music navbar and aplayer config
There are two things:
- add navbar for /music page
- add aplayer configuration about how APlayer is loaded (see cdns) and on which page APlayer will be displayed (see aplayer.hideWhen, aplayer.showWhen).
In the following configuration, APlayer will be displayed only when page is /music, /, /about or post, and on /music page, APlayer will display lyrics on a custom area while will not display lyrics on other pages.
How APlayer is loaded will be determined by cnds. By default, it is loaded from local. If you have fast connection to APlayer's cdn, you can turn cnds.APlayer.enable to true.
1 | navbar: |

create music page
Create file music/index.md under /source/[lang], set content as below.
Content of /source/en/music/index.md.
1 |
|
Content of /source/zh-CN/music/index.md.
1 |
|
set page layout
post.ejs
Update file post.ejs under /themes/arch/layout and add content as below.
1 | <!-- music --> |

Update file layout.ejs under /themes/arch/layout and add content as below.
1 | <!-- 非music页面 --> |

aplayer.ejs
Create file aplayer.ejs under /themes/arch/layout/_patial and set content as below.
- getMode will return mode of APlayer according to _config.yml and current page.
- theme.cdns.APlayer.enable will determine how APlayer is loaded.
- aplayerConfig is option to init APlayer, and displayLrc will move default lyrics to a custom area.
- originAudioList saves audio resource url, including lyrics, cover, audio. You may change it to your own resource url.

1 | <% function getMode(page, showWhen = [], hideWhen = []) { |
dowload APlayer
Download js and css of APlayer to /themes/arch/source/plugins from https://www.jsdelivr.com/package/npm/aplayer.

set page style
aplayer.css
Create file aplayer.css under /themes/arch/source/css and set content as below.
This style is for lyrics custom display area.
1 | .aplayer.aplayer-withlrc .aplayer-info { |
main.styl
Update file main.styl under /themes/arch/source/css and add content as below.
1 | .music-container .custom-lrc-container p.aplayer-lrc-current { |

add translation
Update en.yml and zh-CN.yml under /themes/arch/languages and set content as below.
Content of /themes/arch/languages/en.yaml.
1 | Music: Music |
Content of /themes/arch/languages/zh-CN.yml
1 | Music: 音乐 |
save and restore playing status
This is v2 version of music. Playing status of music (including index, paused, currentTime, loop, order, see in Options ) will remain unchanged when page changes, which is implmented by localStorage. Another method like pjax is also feasible.
At first, I thought it quite easy. Just save to storage before page unloads and get from storage and update APlayer instance after page loads. But, the point is, autoplay may be disallowed depending on your device. When it's disallowed and audio should be playing, you have to hacking it to make audio play (see enalbeAutoplay below).
1 | function canAutoplay(){ |

Another point is, current time of music may not be that from storage. For example, when you switch music, current time should not read from storage. When music is paused, drag the progress bar or click on the lyric row, current time should not be that from storage. So expectedPlayTime is used to record the right current time and seek to it when a music is played at the first time.
1 | player.on('seeked', () => { |
Anyway, it doesn't seem as easy as I thought. If you want your music to resume exactly where you left off, it's best to ensure your device allows autoplay.
Code changes as below.

update audio progress when lyrics clicked
This is v3 version of music. At first I thought it impossible without parsing lyrics myself because time can not accessed when lyric line is clicked. But when I see source code of APlayer, I find parsed lyrics added to APlayer instance, so I can get lyrics of current played music by player.lrc.parsed[player.list.index]
or player.lrc.current
. That's exactly what I need.

Then just add click listener to lrcContainer and seek to the clicked line. But do notice please:
- event target may not be lyric row, so
parent.classList.contains('aplayer-lrc-contents')
is needed to ensure it. - find childIndex by element of clicked row instead of innerText because there may be duplicated lyrics.
1 | function seekToClickedLine(e) { |

Code changes as below.

unable to jump when toc clicked
After APlayer is added, I occasionally find it can not jump when .toc-link
is clicked. From DevTools I find a click listener from APlayer.min.js added to .toc-link
. That's the fault of APlayer.

Then how to fix it? Well, just remove the listener.
However, I want to see whether there is already a solution, so I google it. Well, many results are useless. Luckily, I see this post, it turns out to be smoothscroll's fault. I google wangriyu github
and finally find the original solution 👍 https://wangriyu.github.io/2018/06-Aplayer.html . Using decodeURIComponent
to wrap location.hash or this.hash will fix this bug.

But it won't be helpful when APlayer is loaded from cdn. So I try to solve it by remove click listener of toc-link
.
But there is a problem. A listener must be specific if you want to remove it using removeEventListener(type, listener). In order to get the listener of .toc-link
, I hack addEventListener by using snippet below.
1 | const oldAddEventListener = Element.prototype.addEventListener; |
Then use removeEventListenersByElement to remove all click listener of .toc-link
.
1 | // 修复引入的APlayer.min.js,造成toc-link无法跳转 |
Code changes as below.

unable to update playback progress
When I use hexo server
to start local server, I can't update playback progress by dragging the progress bar or seeking or clicking on the lyric row. Then I learn from Unable to set playback progress, and add a script "server:static": "npm run build && hexo server --static"
to make it work.