📢 新文章推送 · 每周更新优质内容 · 订阅更新 →
向下滚动
开发编程

全局音乐播放器开发实践

AI 智能总结

设计目标

在博客中嵌入音乐播放功能,核心需求:

  1. 独立音乐页面:全功能播放器,包含歌单切换、黑胶唱片动画、歌词
  2. 全局迷你挂件:右下角小播放器,切换页面不中断播放
  3. 跨页面状态同步:歌曲进度、播放状态在所有页面共享

技术选型

选择 APlayer 作为播放器引擎,它是一个轻量级的开源 HTML5 音乐播放器。

1<link rel="stylesheet" href="/css/APlayer.min.css">
2<script src="/js/APlayer.min.js"></script>

初始化:

 1const ap = new APlayer({
 2  container: document.getElementById('player'),
 3  mini: false,
 4  autoplay: false,
 5  theme: '#f44336',
 6  loop: 'all',
 7  order: 'list',
 8  preload: 'auto',
 9  volume: 0.7,
10  mutex: true,
11  listFolded: false,
12  listMaxHeight: 250,
13  lrcType: 3,
14  audio: [
15    {
16      name: '歌名',
17      artist: '歌手',
18      url: '/music/song.mp3',
19      cover: '/images/music/cover.jpg',
20      lrc: '/music/song.lrc'
21    }
22  ]
23});

黑胶唱片旋转动画

唱片旋转是音乐页面的视觉亮点。

HTML 结构

1<div class="vinyl-container">
2  <div class="vinyl-cover"></div>
3  <div class="vinyl-disc">
4    <div class="vinyl-label"></div>
5  </div>
6  <div class="vinyl-arm"></div>
7</div>

CSS 动画

 1.vinyl-disc {
 2  animation: vinylSpin 3s linear infinite paused;
 3}
 4
 5.vinyl-disc.playing {
 6  animation-play-state: running;
 7}
 8
 9@keyframes vinylSpin {
10  0%   { transform: rotate(0deg); }
11  100% { transform: rotate(360deg); }
12}

播放时 animation-play-state: running,暂停时 paused,唱片旋转和唱针角度联动切换。

歌词同步

APlayer 内建 LRC 歌词解析能力。配置 lrcType: 3 并提供 LRC 文件 URL:

1[ti:歌名]
2[ar:歌手]
3[00:15.20]第一句歌词
4[00:20.50]第二句歌词
5[00:28.30]第三句歌词

歌词滚动区域自动追踪当前播放句,高亮绿色。

跨页面状态同步(关键)

全局音乐播放器的核心挑战是:用户从文章页切换到首页时,音乐不能中断。

SessionStorage 方案

APlayer 是页面级实例,页面跳转后实例被销毁,音乐中断。解决方法是:

  1. 将音乐挂件放在固定框架(iframe 或独立 JS 上下文)
  2. 或者使用更简单的方案:创建一个隐藏的 iframe 承载 APlayer,所有页面通过 postMessage 与它通信
 1// 检查是否已存在全局播放器 iframe
 2let playerFrame = document.getElementById('global-player-frame');
 3
 4if (!playerFrame) {
 5  playerFrame = document.createElement('iframe');
 6  playerFrame.id = 'global-player-frame';
 7  playerFrame.src = '/player.html';
 8  playerFrame.style.display = 'none';
 9  document.body.appendChild(playerFrame);
10}
11
12function playSong(songIndex) {
13  playerFrame.contentWindow.postMessage({
14    action: 'play',
15    songIndex: songIndex
16  }, '*');
17}

迷你挂件

右下角迷你挂件显示当前歌曲名称和播放/暂停按钮:

1<div class="mini-player-widget" id="mini-player">
2  <div class="mini-cover" id="mini-cover"></div>
3  <div class="mini-info">
4    <span class="mini-title" id="mini-title">未在播放</span>
5    <span class="mini-artist" id="mini-artist"></span>
6  </div>
7  <button class="mini-toggle" id="mini-toggle"></button>
8</div>

迷你挂件通过 postMessage 与 iframe 通信,歌曲信息实时同步。

页面类型识别

音乐页面本身有完整的播放器,不需要迷你挂件;其他页面才显示迷你挂件:

1if (window.location.pathname === '/music/') {
2  // 音乐页面:直接操作完整播放器
3} else {
4  // 其他页面:显示迷你挂件 + iframe
5  initMiniWidget();
6}

多平台歌单

APlayer 原生支持加载远程音乐文件。通过预提取 QQ音乐、网易云音乐、酷狗音乐的歌单接口,将歌曲列表转换为 APlayer 音频数组。歌单 ID 在配置文件中设置,切换歌单时刷新音频列表即可。

性能注意

注意点说明
音频预加载preload: 'auto' 会加载整首歌,建议改为 'metadata'
自动播放限制浏览器策略禁止无用户交互的自动播放,需要用户首次手动点击
iframe 通信postMessage 消息体积小,对性能无影响
迷你挂件渲染仅在非音乐页面渲染,减少不必要开销
专题系列 Lumin Blog 优化
11 / 22
版权声明

本文作者 Lumin

本文链接 https://www.zhengquan.xyz/code/global-music-player/

许可协议 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!

请作者喝杯咖啡 ☕

  • 微信打赏
    微信支付
  • 支付宝打赏
    支付宝
点击按钮查看打赏二维码
🎁 推荐工具
试试这些实用在线工具,提升工作效率
前往工具集 →

留言评论

期待你的想法

评论加载中