APlayer

使用APlayer引入网站音乐播放器

以下由Hugo的stack主题演示,其他的可作为参考。

修改方法来源:莱特雷-letere

引入APlayer

  1. 在Hugo工作文件夹的layouts/partials/footer文件夹中新建一个文件,命名为 aplayer.html

  2. aplayer.html中输入以下内容:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.css">
<div id="aplayer"></div>
<script src="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.js"></script>

<script>
    const ap = new APlayer({
        container: document.getElementById('aplayer'),
        fixed: true,
        listFolded: true,
        lrcType: 3,
        audio: [{
            name: 'example',
            artist: 'example',
            url: 'https://example.mp3',
            lrc: 'example.lrc',
            cover: 'example.png'
        }]
    });
</script>
  1. layouts/partials/footer中新建一个文件夹,命名为custom.html,在其中输入:
1
{{ partialCached "footer/aplayer.html" . }}

这样,aplayer就成功导入到网页中了。

修改APlayer样式

实现播放进度保存

 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
29
30
31
32
33
34
35
36
<script>
    /**
    * 页面销毁前监听
    */
    window.onbeforeunload = () => {
        // 将播放信息用对象封装,并存入到localStorage中
        const playInfo = {
            index: ap.list.index,
            currentTime: ap.audio.currentTime,
            paused: ap.paused
        };
        localStorage.setItem("playInfo", JSON.stringify(playInfo));
    };

    /**
        * 页面加载后监听
        */
    window.onload = () => {
        // 从localStorage取出播放信息
        const playInfo = JSON.parse(localStorage.getItem("playInfo"));
        if (!playInfo) {
            return;
        }
        // 切换歌曲
        ap.list.switch(playInfo.index);
        // 等待500ms再执行下一步(切换歌曲需要点时间,不能立马调歌曲进度条)
        setTimeout(() => {
            // 调整时长
            ap.seek(playInfo.currentTime);
            // 是否播放
            if (!playInfo.paused) {
                ap.play()
            }
        }, 500);
    };
</script>

实现隐藏播放器图标

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<style>
    .aplayer-fixed.aplayer-narrow .aplayer-body {
        left: -70px !important;
        /* 默认情况下缩进左侧70px,只留一点箭头部分 */
    }

    .aplayer-fixed.aplayer-narrow .aplayer-body:hover {
        left: 0 !important;
        /* 鼠标悬停是左侧缩进归零,完全显示按钮 */
    }
</style>

导入pjax实现音乐不间断播放

pjax是一项页面切换不加载技术,可实现切换网页后音乐不间断。

导入pjax

  1. layouts/partials/footer中新建文件,命名为pjax.html.

  2. 在文件中写入代码:

1
2
3
4
5
6
7
8
<script src="https://cdn.jsdelivr.net/npm/pjax/pjax.min.js"></script>
<script>
    var pjax = new Pjax({
        selectors: [
            ".main-container"
        ]
    })
</script>

这样pjax就成功导入网页中了。

修复网页样式

pjax.html中加入以下内容:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<script>
    pjax._handleResponse = pjax.handleResponse;
    pjax.handleResponse = function(responseText, request, href, options) {
        if (request.responseText.match("<html")) {
            if (responseText) {
                // 将新页面的html字符串解析成DOM对象
                let newDom = new DOMParser().parseFromString(responseText, 'text/html');
                // 获取新页面中body的className,并设置回当前页面
                let bodyClass = newDom.body.className;
                document.body.setAttribute("class", bodyClass)
                // 放行,交给pjax自己处理
                pjax._handleResponse(responseText, request, href, options);
            }
        } else {
            // handle non-HTML response here
        }
    }
</script>

修复主题切换

pjax.html中加入以下内容。

1
2
3
4
5
6
<script>
    document.addEventListener('pjax:complete', () => {
        // Stack脚本初始化
        window.Stack.init();
    })
</script>

修复搜索

  1. 修改assets/ts/search.tsx代码,封装方法并export
 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
/**
 * 记得把window.addEventListener('load' ...这部分代码注释掉
 * 初始化工作交给Stack.init()处理了,不需要这个了
 */  
...
function searchInit() {
    let search = document.querySelector('.search-result');
    if (search) {
        const searchForm = document.querySelector('.search-form') as HTMLFormElement,
            searchInput = searchForm.querySelector('input') as HTMLInputElement,
            searchResultList = document.querySelector('.search-result--list') as HTMLDivElement,
            searchResultTitle = document.querySelector('.search-result--title') as HTMLHeadingElement;

        new Search({
            form: searchForm,
            input: searchInput,
            list: searchResultList,
            resultTitle: searchResultTitle,
            resultTitleTemplate: window.searchResultTitleTemplate
        });
    }
}

export {
    searchInit
}
  1. 修改assets/ts/main.ts,引入搜索初始化方法并调用
1
2
3
4
5
6
7
8
9
...
import { searchInit } from "ts/search";
let Stack = {
    init: () => {
        ...
        // 调用search脚本初始化方法
        searchInit();
    }
}
  1. tsx 类型的文件引入方式有点特殊,需要我们修改main.ts的引入方式,修改layouts/partials/footer/components/script.html,改法参考layouts/page/search.html,把JSXFactorycreateElement补充上就好

  2. 修改assets/ts/search.tsx,在动态渲染数据方法末尾让pjax重新解析文档

1
2
3
4
5
6
7
8
9
private async doSearch(keywords: string[]) {
    ...
    /* 
    方法末尾,让pjax重新解析文档数据,识别动态渲染的数据
    虽然当前文件没有pjax对象,但最后静态页面会生成一个整体的js文件
    pjax对象那时就能识别到,就可成功调用
    */
    pjax.refresh(document);
}

修复Latex

  1. 修改layouts/partials/article/components/math.html,添加一个元素标签,便于判断文档是否使用了KaTeX
1
<div class="math-katex"></div>
  1. layouts/partials/footer/custom.html中引入以下代码:
 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
29
30
31
32
33
34
35
36
<script>
    async function renderKaTeX() {
        // 判断当前页面是否有KateX
        let katex = document.querySelector(".math-katex");
        if (!katex) {
            return;
        }
        // 等待函数加载成功后,再执行渲染方法
        while (typeof renderMathInElement !== 'function') {
            await delay(500);
        }        
        // KaTeX渲染方法
        renderMathInElement(document.body, {
            delimiters: [
                { left: "$$", right: "$$", display: true },
                { left: "$", right: "$", display: false },
                { left: "\\(", right: "\\)", display: false },
                { left: "\\[", right: "\\]", display: true }
            ],
            ignoredClasses: ["gist"]
        });
    }
    
    /**
     * 同步延迟
     */
    function delay(time) {
        return new Promise(resolve => {
            setTimeout(resolve, time)
        })
    }

    document.addEventListener('pjax:complete', () => {
        renderKaTeX();
    })
</script>

取消pjax的时间戳

pjax会默认给网页加上时间戳,具体为表现为?t=1724141234567的样式,这样会使页面间的跳转出现问题,建议关闭。

pjax.html中引入:

1
2
3
4
5
6
7
<script>
    document.addEventListener('DOMContentLoaded', function () {
        if (window.pjax) {
            window.pjax.options.cacheBust = false; // 关闭时间戳参数
        }
    });
</script>
网站总访客数:Loading

使用 Hugo 构建
主题 StackJimmy 设计