根据专辑封面自动提取主题色
效果
封面自适应主题色是指:每首歌曲有自己的封面图,播放器根据封面图的主色调自动设置主题色。当切换歌曲时,主题色会平滑过渡到新封面的主色。
这个功能需要额外引入 color-thief.js 库——它负责从图片中提取主色调。
引入顺序
<!-- 1. APlayer CSS -->
<link rel="stylesheet" href="APlayer.min.css">
<!-- 2. 播放器容器 -->
<div id="aplayer"></div>
<!-- 3. APlayer JS -->
<script src="APlayer.min.js"></script>
<!-- 4. color-thief.js(放在 APlayer 之后) -->
<script src="color-thief.umd.js"></script>
<!-- 5. 初始化代码 -->
<script>
// 见下文完整代码
</script>
完整实现代码
const ap = new APlayer({
container: document.getElementById('aplayer'),
theme: '#e9e9e9', // 默认主题色
audio: [
{ name: '歌曲一', artist: 'A', url: '1.mp3', cover: '1.jpg' },
{ name: '歌曲二', artist: 'B', url: '2.mp3', cover: '2.jpg' },
{ name: '歌曲三', artist: 'C', url: '3.mp3', cover: '3.jpg' }
]
});
// 初始化 ColorThief
const colorThief = new ColorThief();
const image = new Image();
const xhr = new XMLHttpRequest();
function setTheme(index) {
// 如果这首歌已有手动设置的 theme,优先使用
if (ap.list.audios[index].theme) return;
xhr.onload = function() {
const coverUrl = URL.createObjectURL(this.response);
image.onload = function() {
// 从封面图提取主色
const color = colorThief.getColor(image);
// 设置为 APlayer 的主题色
ap.theme(`rgb(${color[0]}, ${color[1]}, ${color[2]})`, index);
URL.revokeObjectURL(coverUrl);
};
image.crossOrigin = 'Anonymous';
image.src = coverUrl;
};
xhr.open('GET', ap.list.audios[index].cover, true);
xhr.responseType = 'blob';
xhr.send();
}
// 首次加载时为第一首歌设置主题色
setTheme(ap.list.index);
// 切歌时重新提取
ap.on('listswitch', setTheme);
代码逻辑说明
- 初始化一个 ColorThief 实例
- 定义
setTheme(index)函数:下载封面图 → 提取主色 → 设置主题色 - 首次加载时为当前播放歌曲(或第一首)提取主题色
- 监听
listswitch事件,每次切歌都重新提取
CORS 注意事项
封面图如果是跨域资源,需要目标服务器允许跨域访问。XMLHttpRequest 会发送跨域请求,如果目标服务器没有返回正确的 CORS 头,请求会失败。
解决方法:
- 确保封面图服务器返回
Access-Control-Allow-Origin头 - 或者把封面图放到自己的服务器上(同源)
性能考虑
提取颜色需要下载封面图并解码,这是一个有代价的操作。如果图片很大(比如 4000x4000),可以先压缩一下封面图再提取。
APlayer 自己对封面图没有尺寸要求,但 color-thief 处理大图会比较慢。建议封面图控制在 800x800 以内。
简化方案:只为有手动 theme 的歌曲跳过
如果你想让部分歌曲用自动提取的颜色、部分歌曲用手动指定的颜色,代码已经帮你处理了:检查 ap.list.audios[index].theme 是否存在,有则跳过自动提取。
audio: [
{ name: '歌曲一', cover: '1.jpg' }, // 自动提取颜色
{ name: '歌曲二', cover: '2.jpg', theme: '#333' }, // 强制深色主题
{ name: '歌曲三', cover: '3.jpg' } // 自动提取颜色
]