demo展示:https://kankan.fun/assets/vue/music/chenyifa/gzxbz.html
代码下载:https://github.com/kankanol1/gzwbz
直接打包下载或者Git命令下载。

git clone https://github.com/kankanol1/gzwbz

歌词案例

本例主要对 lrc 歌词进行分割,然后对歌词时间和播放时间进行对比,选择是否显示歌词。

效果图片

在这里插入图片描述

最开始的歌词算法

 function showLrc() {
        for (let i = 0; i < result.length-1; i++) {
            let curTime = myAudio.currentTime;//获取当前的播放时间
            if ((curTime >result[i][0]) && (curTime<result[i+1][0]) && document.getElementById("lyric").innerHTML !== result[i][1]) {
                //播放时间大于对应歌词时间小于下一句歌词时间就显示当前歌词
                document.getElementById("lyric").innerHTML = result[i][1];
                break;//找到对应歌词就停,不停的话,呵呵。。。
            }
        }
    }

一秒要对所有歌词时间判断5次,会过量消耗CPU

改进后的代码

解决过度循环,减少CPU占用.

function showLrc() {
        let curTime = myAudio.currentTime;//获取当前的播放时间
        if(flagN<result.length-1){
            if ((curTime >result[flagN][0]) && (curTime<result[flagN+1][0]) && document.getElementById("lyric").innerHTML !== result[flagN][1]) {
                document.getElementById("lyric").innerHTML = result[flagN][1];
                flagN = flagN+1;
            }
        }else{
            if(curTime >result[flagN][0]){
                document.getElementById("lyric").innerHTML = result[flagN][1];
                if(flagN === result.length-1) flagN = 0;
            }
        }
    }

想去掉条件语句

更优化的代码

解决去掉条件语句,需要对歌词进行稍微改造一下,在歌词最后加一个空的歌词时间 例如 ’[04:34.34] '. 具体案例见 代码.

  function showLrc() {
  	let curTime = myAudio.currentTime;//获取当前的播放时间
	//监听快进,回退
  	if( curTime>result[flagN+1][0] ||  curTime<result[flagN][0] ){
            for(let i=0;i<result.length;i++){
                if((curTime >result[i][0]) && (curTime<result[i+1][0])) flagN = i;
            }
        }
     //正常的循环次序
    if ((curTime >result[flagN][0]) && (curTime<result[flagN+1][0]) && document.getElementById("lyric").innerHTML !== result[flagN][1]) {
            document.getElementById("lyric").innerHTML = result[flagN][1];
            flagN = (flagN===result.length-2) ? 0 : flagN+1;
        }
    }

解决lrc歌词不一致的问题

function getLrc() {
	 //解决'[00:29.12]我在家中来等候\n' 类型的歌词
	let timeReg1 = /\[\d{2}:\d{2}\.\d{2}\]/g;// || /\[\d{2}:\d{2}\.\d{3}\]/g;//匹配时间的正则表达式
     //解决'[00:29.122]我在家中来等候\n' 类型的歌词
    let timeReg2 = /\[\d{2}:\d{2}\.\d{3}\]/g;// || /\[\d{2}:\d{2}\.\d{3}\]/g;//匹配时间的正则表达式
    for (let i=0;i<lrc.length;i++) {
         let time;
          let value;
         
          if(lrc[i].match(timeReg1)){
              time = lrc[i].match(timeReg1);
              value = lrc[i].replace(timeReg1, "")
          }
          if(lrc[i].match(timeReg2)){
              time = lrc[i].match(timeReg2);
              value = lrc[i].replace(timeReg2, "")
          }
          for (let j=0;j<time.length;j++ ) {
              let t = time[j].slice(1, -1).split(":"); //t[0]分钟,t[1]秒
              let timeArr = parseInt(t[0], 10) * 60 + parseFloat(t[1]);
              result.push([timeArr, value]);//以[时间(秒),歌词]的形式存进result
          }
     }
    setInterval(showLrc, 100);//设置定时,每200毫秒更新一下
}

代码

主要给一些展示,以供理解,全部代码请 点击这里 下载。如果代码和教程不一样,请参考 教程进行修改(强迫你去学习)。

HTML 代码

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1"/>
    <link rel="shortcut icon" href="./favicon.ico" type="image/x-icon" />
    <title>世界第一等</title>
    <script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
    <link rel="stylesheet" href="./css/item.css">
</head>
<body class="gzxbz">
<div class="box">
    <div class="info"></div>
    <audio src="./mp3/gzxbz.mp3"  autoplay loop controls id="mp">抱歉你的浏览器版本out了,去升级吧</audio>
    <div id="lyric"></div>
</div>
<script src="./js/gzxbz.js"></script>
<script src="./js/lrc.js"></script>
</body>
</html>

歌词lrc

放入到了js文件中,可以理解为JSON数据

let str ='[00:02.18]公子向北走\n' +
    '[00:04.35]词:佚名\n' +
    '[00:05.92]改编:李亮节\n' +
    '[00:07.83]曲:李亮节\n' +
    '[00:09.78]音乐制作人:刘骏\n' +
    '[00:11.75]演唱:李春花\n' +
    '[00:13.65]录音室:天津盛音虔栈文化工作室\n' +
    '[00:15.58]发行公司:杭州回声文化艺术策划有限公司\n' +
    '[00:17.58]\n' +
    '[00:19.49]小女子不才\n' +
    '[00:23.29]未得公子青睐\n' +
    '[00:27.18]扰公子良久\n' +
    '[00:30.97]公子勿怪\n' +
    '[00:34.91]公子向北走\n' +
    '[00:38.74]小女子向南瞧\n' +
    '[00:42.70]此生就此别过了\n' +
    '[00:46.59]难以忘怀\n' +
    '[00:54.26]愿你三冬暖\n' +
    '[00:58.09]愿你春不寒\n' +
    '[01:01.98]愿你天黑有灯\n' +
    '[01:05.81]下雨有伞\n' +
    '[01:09.71]愿你善其身\n' +
    '[01:13.60]愿你遇良人\n' +
    '[01:17.53]暖色浮余生\n' +
    '[01:21.58]有好人相伴\n' +
    '[01:25.47]\n' +
    '[01:56.23]所有爱慕之意\n' +
    '[02:00.08]止于唇齿间\n' +
    '[02:04.06]掩于岁月\n' +
    '[02:07.96]匿于将来\n' +
    '[02:11.85]与君今生无缘\n' +
    '[02:15.57]请无需挂念\n' +
    '[02:19.45]雨打芭蕉\n' +
    '[02:23.32]无可无奈\n' +
    '[02:31.08]愿你三冬暖\n' +
    '[02:34.88]愿你春不寒\n' +
    '[02:38.80]愿你天黑有灯\n' +
    '[02:42.65]下雨有伞\n' +
    '[02:46.58]愿你善其身\n' +
    '[02:50.46]愿你遇良人\n' +
    '[02:54.31]暖色浮余生\n' +
    '[02:57.63]有好人相伴\n' +
    '[03:02.16]愿你三冬暖\n' +
    '[03:05.92]愿你春不寒\n' +
    '[03:09.77]愿你天黑有灯\n' +
    '[03:13.58]下雨有伞\n' +
    '[03:17.48]愿你善其身\n' +
    '[03:21.31]愿你遇良人\n' +
    '[03:25.22]暖色浮余生\n' +
    '[03:28.53]有好人相伴\n' +
    '[03:35.05]小女子不才\n' +
    '[03:38.73]未得公子青睐\n' +
    '[03:42.69]扰公子良久\n' +
    '[03:46.59]公子\n' +
    '[03:50.16]勿怪\n' +
    '[03:51.72]\n' +
    '[03:54.01]';
let data = {
    name:'李春花',
    song:'公子向北走'
};

核心JS

涉及字符串分隔、DOM操作、正则表达、计时器、三目运算等.

let arr = str.split('\n');
$(document).ready(function () {
    let lrc = []; //创建歌词数组;
    lrc = arr;
    let myAudio = $("audio")[0];
    let result = [];
    getLrc();
    let flagN = 0;
    function getLrc() {
        let timeReg = /\[\d{2}:\d{2}\.\d{2}\]/g;//匹配时间的正则表达式
        for (let i=0;i<lrc.length;i++) {
            let time = lrc[i].match(timeReg); //获取歌词里的时间
            let value = lrc[i].replace(timeReg, ""); //获取纯歌词文本
            for (let j=0;j<time.length;j++ ) {
                let t = time[j].slice(1, -1).split(":"); //t[0]分钟,t[1]秒
                let timeArr = parseInt(t[0], 10) * 60 + parseFloat(t[1]);
                result.push([timeArr, value]);//以[时间(秒),歌词]的形式存进result
            }
        }
        setInterval(showLrc, 100);//设置定时,每200毫秒更新一下
    }
    function showLrc() {
        let curTime = myAudio.currentTime;//获取当前的播放时间
        if ((curTime >result[flagN][0]) && (curTime<result[flagN+1][0]) && document.getElementById("lyric").innerHTML !== result[flagN][1]) {
            document.getElementById("lyric").innerHTML = result[flagN][1];
            flagN = (flagN===result.length-2) ? 0 : flagN+1;
        }
    }


    /*function showLrc() {
        let curTime = myAudio.currentTime;//获取当前的播放时间
        if(flagN<result.length-1){
            if ((curTime >result[flagN][0]) && (curTime<result[flagN+1][0]) && document.getElementById("lyric").innerHTML !== result[flagN][1]) {
                document.getElementById("lyric").innerHTML = result[flagN][1];
                flagN = flagN+1;
            }
        }else{
            if(curTime >result[flagN][0]){
                document.getElementById("lyric").innerHTML = result[flagN][1];
                if(flagN === result.length-1) flagN = 0;
            }
        }
    }*/
//上面的条件语句可以去掉,在歌词最后加一个 空的歌词时间 例如 [04:34.34]

    //每次都要繁琐循环歌词,消耗CPU资源 ,上面的代码大大的降低了CPU消耗
/*    function showLrc() {
        for (let i = 0; i < result.length-1; i++) {
            let curTime = myAudio.currentTime;//获取当前的播放时间
            if ((curTime >result[i][0]) && (curTime<result[i+1][0]) && document.getElementById("lyric").innerHTML !== result[i][1]) {
                //播放时间大于对应歌词时间小于下一句歌词时间就显示当前歌词
                document.getElementById("lyric").innerHTML = result[i][1];
                break;//找到对应歌词就停,不停的话,呵呵。。。
            }
        }
    }*/
});

let oInfo = document.querySelector('.info');
let h1  = document.createElement('h1');
h1.innerHTML = data.song;
let p = document.createElement('p');
p.className = 'name';
p.innerHTML  = data.name;
oInfo.appendChild(h1);
oInfo.appendChild(p);

核心问题

主要是解决歌词正常显示的时候,还要做到减少后台计算,较少过度占用CPU资源,优化无处不在,嘻嘻.

个人主页

冰原狼主页:https://kankan.fun/
CSDN主页:https://blog.csdn.net/qq_38025939/
Github主页:https://github.com/kankanol1

明天的你一定会感谢现在拼命的自己!

Logo

前往低代码交流专区

更多推荐