先看原生lrc歌词的解析,我创建了一个函数,全程仅用10行代码将歌词转换成花潮格式的lrc歌词数组:
var lrcAr = [];
var getLrcAr = (text) => {
var ar = text.trim().split('\n');
ar.sort();
var reg = /\[(\d+)[.:](\d+)[.:](\d+)\](.*)/;
ar.forEach(item => {
let result = item.match(reg);
let tmsg = parseInt(result[1]) * 60 + parseInt(result[2]) + parseInt(result[3]) / 1000;
lrcAr.push([tmsg, result[4].trim()]);
});
};
函数所需参数 text 是原生lrc歌词字符串。函数先将歌词去除头尾空白后按行拆分为数组并进行排序,然后逐行按正则进行解析、提取所需信息再加入事先声明的全局数组变量 lrcAr。正则表达式的设计是简化处理机制的关键,代码中 reg 变量值是一个正则,它分成四个提取组,匹配成功后将拿到5个数组元素的结果,后四个对应于分、秒、毫秒和歌词。
传参执行函数,拿到的结果是花潮格式的lrcAr数组,这意味着众多歌词同步的插件可以派上用场了。
需要注意的是:
一、支持的原生lrc歌词格式
① [mm:ss:ff]歌词
② [mm:ss.ff]歌词
③ [mm.ss.ff]歌词
④ [mm.ss:ff]歌词
前两种较为常见,后两种偶尔会见到。这些格式的原生lrc歌词,可以混合出现在歌词中,函数都能处理。
二、不支持复合时间信息原生lrc歌词格式,例如下面这两种:
① [mm:ss:ff][mm:ss:ff]歌词
② [mm:ss:ff][mm:ss:ff][mm:ss:ff]歌词
如果碰上这类结果的复合时间信息的歌词,请手动将其分开(歌词相同),顺序不用管。
三、原生歌词的写法
可以分行写,一行一句;也可以使用分隔符 \n 衔接各句歌词。例如:
最后给出一个应用实例,无插件依赖。代码:
<style>
#tz { margin: 20px auto; width: 740px; height: 300px; border: 1px solid gray; position: relative; }
#tz::before { content: attr(data-lrc); position: absolute; bottom: 0; width: 100%; height: 60px; text-align: center; font: normal 24px/60px sans-serif; color: transparent; background: repeating-linear-gradient(to right, red, green, blue, green, red) 50%/200px 60px; -webkit-background-clip: text; }
#player { position: absolute; top: 30px; left: calc(50% - 61px); cursor: pointer; animation: rot 6s linear infinite var(--state); }
@keyframes rot { to { transform: rotate(360deg); } }
</style>
<div id="tz" data-lrc="HUACHAO">
<audio id="aud" src="https://music.163.com/song/media/outer/url?id=1429962105" autoplay loop></audio>
<img id="player" src="https://638183.freep.cn/638183/t23/btn/plum.png" alt="" title="播放/暂停" />
</div>
<script>
var curkey = 0, lrcAr = [];
var getAr = (text) => {
var ar = text.trim().split('\n');
ar.sort();
var reg = /\[(\d+)[.:](\d+)[.:](\d+)\](.*)/;
ar.forEach(item => {
let result = item.match(reg);
let tmsg = parseInt(result[1]) * 60 + parseInt(result[2]) + parseInt(result[3]) / 1000;
lrcAr.push([tmsg, result[4].trim()]);
});
};
var mState = () => {
tz.style.setProperty('--state', ['running','paused'][+aud.paused]);
player.title = ['暂停','播放'][+aud.paused];
//其它控制代码
};
aud.onseeked = () => curkey = 0;
aud.onplaying = aud.onpause = () => mState();
aud.ontimeupdate = () => {
if(curkey > lrcAr.length - 1) return;
if(aud.currentTime >= lrcAr[curkey][0]) {
tz.dataset.lrc = lrcAr[curkey][1];
curkey ++;
}
};
player.onclick = () => aud.paused ? aud.play() : aud.pause();
var lrc = `
[00:00:900]张子铭 - 一生最爱
[00:20.180]向雪怀作词,伍思凯作曲
[00:22.180]吉他:白毛
[00:23.678]如果痴痴的等某日终于可等到一生中最爱
[00:31.426]谁介意你我这段情每每碰上了意外不清楚未来
[00:38.678]何曾愿意 我心中所爱
[00:45.927]每天要孤单看海
[00:54.426]宁愿一生都不说话都不想讲假说话欺骗你
[01:02.177]留意到你我这段情你会发觉间隔着一点点距离
[01:09.426]无言地爱 我偏不敢说
[01:17.676]说一句想跟你一起
[01:24.427]OOOH OOH
[01:28.926]如真 如假 如可分身饰演自己
[01:36.674]会将心中的温柔献出给你唯有的知己
[01:44.174]如痴 如醉 还盼你懂珍惜自己
[01:51.675]有天即使分离我都想你我 真的想你
[02:27.172]宁愿一生都不说话都不想讲假说话欺骗你
[02:35.172]留意到你我这段情你会发觉间隔着一点点距离
[02:42.423]无言地爱 我偏不敢说
[02:50.671]说一句想跟你一起
[02:57.424]OOOH OOH
[03:01.922]如真 如假 如可分身饰演自己
[03:09.422]会将心中的温柔献出给你唯有的知己
[03:17.171]如痴 如醉 还盼你懂珍惜自己
[03:24.671]有天即使分离我都想你我 真的想你
[03:36.422]如真 如假 如可分身饰演自己
[03:43.922]会将心中的温柔献出给你唯有的知己
[03:51.670]如痴 如醉 还盼你懂珍惜自己
[03:59.421]有天即使分离我都想你我 真的想你
[04:11.674]如果痴痴的等某日终于可等到一生中最爱
`;
getAr(lrc);
</script>