开源项目:音乐播放器 - 滚动歌词

5,748 阅读3分钟
一、格式化歌词

接口返回的歌曲歌词是字符串形式,需要把格式格式化后提取相关信息用于实现滚动歌词。

歌词示例:

[00:00.000] 作词 : 于正\n[00:01.000] 作曲 : 谭旋\n[00:27.129]天生我才必有用\n 

格式化后的数据示例:


[ 
    {time: 0.000, text: '作词 : 于正'}, 
    {time: 1.000, text: '作曲 : 谭旋'}, 
    {time: 27.129, text: '天生我才必有用'}, 
] 

格式化使用的函数:


/**

* 格式化时间字符串为时间,时间单位为秒

* @param timeString 时间字符串,格式为: mm:ss:ss, 如: 00:01:404

* @returns

*/

export const formatTimeToNumber = (timeString: string) => {

    let time = 0;

    if (timeString) {

    const splitArr = timeString.split(":").map((item) => Number(item));

    return splitArr[0] * 60 + splitArr[1];

    }

    return time;

};



/**

* 格式化歌词字符串为"时间-歌词"格式的数组

* @param lyric 歌词字符串

* @returns

*/

export const formatLyric = (lyric: string) => {

    const lyricParts = lyric.split("\n").filter((item) => item);

    return lyricParts.map((item) => {

        const splitItems = item.split("]");

        const lyricItem: ILyric = {

        time: formatTimeToNumber(splitItems[0].slice(1)),

        text: splitItems[1],

        };

        return lyricItem;

    });

};

二、歌词滚动

实现歌词滚动需要知道当前歌曲播放的实时时间,然后根据实时时间和歌词数组里面歌词的 time字段进行比较,获取到当前歌曲播放到了那句歌词,然后根据歌词去计算滚动的距离。

获取歌曲当前播放的时间,需要在播放器组件里处理,存储到状态管理里面供全局使用,我使用的是vuex。代码如下:

// 获取当前播放时间

ele.ontimeupdate = () => {

    _.debounce(() => {

    store.commit("player/setCurrentTime", ele.currentTime.toFixed(3));

    }, 1000)();

};

歌曲播放的时候,状态currentTime会不停地更新。但是即便如此currentTime也并不一定会和歌词数组里面的time字段相等,因为此处currentTime是一个6位小数的浮点数,事件ontimeupdate的触发也不是一定的,所以currentTime和歌词中的歌词时间不一定完全匹配。

所以在比较的时候,只需要比较到秒级,不需要精确到毫秒级。另外,currentTime和歌词时间的比较有2种情况:

  1. currentTime和某句歌词时间相等,歌词的索引就是当前播放的歌词;
  2. currentTime时间小于某句歌词时间,上一句歌词就是当前播放的歌词;

通过遍历获取到当前播放的歌曲的歌词的索引后,就可以获取到当前播放歌曲到顶部的距离。具体逻辑是:

  1. 通过document.querySelectorAll(".lyric-item")获取所有歌词的元素,根据每个元素的clientHeight获取元素的高度;
  2. 根据当前播放歌词的索引,获取当前歌词元素到顶部的距离,并设置滚动到顶部的距离;
  3. 同时根据当前歌词的索引,就可以设置歌词的高亮样式;
  4. 同时,根据元素的高度还可以设置当前歌词居中;
三、项目地址和代码

歌词滚动的功能用文字描述不太方便,想要了解更多建议直接查看GitHub上的源码。 
项目在线访问地址:music-player.immortalboy.cn/ 
github项目地址:github.com/programmerm… 
滚动歌词组件github地址:github.com/programmerm…

注意:

  1. 项目的前端页面部署到了netlify,国内访问可能会卡顿,请谅解;
  2. 滚动歌词的功能在歌曲详情里,请点击在线访问地址的页面底部音乐播放器的歌曲封面或者歌曲名,进入到歌曲详情们可以观看滚动歌曲效果(歌曲播放后才会滚动);