js实现歌词跟随滚动

 

基本上仿写了这个,但是上面那个实现的效果里没有实现快进和后退的功能,我在上面的基础上,增加了快进和后退

不多说,直接上代码

样式部分

<style>
        * {
            margin: 0;
            padding: 0;
        }

        .lrc_content {
            display: none;
        }

        .box {
            height: 300px;
            background: url(banner.png) no-repeat;
            background-size: 100%;
        }

        .cover {
            width: 100%;
            height: 100%;
            background-color: rgba(0, 0, 0, .5);
            text-align: center;
            color: #fff;
            overflow: hidden;
            position: relative;
            font-family: "楷体";
        }

        ul {
            width: 100%;
            position: absolute;
            top: 0;
            left: 0;
            list-style: none;
        }

        .cover li {
            width: 100%;
            height: 30px;
            line-height: 30px;
            text-align: center;
        }

        .active {
            color: greenyellow;
            font-weight: bold;
            font-size: 20px;
            text-align: center;

        }
    </style>

HTML部分,歌词的数据是从lrc(歌词文件)中提取出来的,后续可能还有一个案例是从json提取数据显示歌词,主要是这些数据是带有时间轴的啊

<div class="lrc_content">
        <p>[ti:沙漠骆驼]</p>
        <p>[ar:展展与罗罗]</p>
        <p>[al:沙漠骆驼]</p>
        <p>[by:0]</p>
        <p>[offset:0]</p>
        <p>[00:00.59]沙漠骆驼 - 展展与罗罗</p>
        <p>[00:02.97]词:展展与罗罗</p>
        <p>[00:04.46]曲:展展与罗罗</p>
        <p>[00:26.45]我要穿越这片沙漠</p>
        <p>[00:28.51]找寻真的自我</p>
        <p>[00:30.50]身边只有一匹骆驼陪我</p>
        <p>[00:34.96]这片风儿吹过</p>
        <p>[00:37.15]那片云儿飘过</p>
        <p>[00:39.26]突然之间出现爱的小河</p>
        <p>[00:43.63]我跨上沙漠之舟</p>
        <p>[00:45.71]背上烟斗和沙漏</p>
        <p>[00:47.92]手里还握着一壶烈酒</p>
        <p>[00:52.35]漫长古道悠悠</p>
        <p>[00:54.51]说不尽喜怒哀愁</p>
        <p>[00:56.56]只有那骆驼奔忙依旧</p>
        <p>[01:01.08][02:23.81][04:13.30]什么鬼魅传说</p>
        <p>[01:03.12][02:25.94][04:15.20]什么魑魅魍魉妖魔</p>
        <p>[01:05.43][02:28.30][04:17.47]只有那鹭鹰在幽幽的高歌</p>
        <p>[01:09.81][02:32.61][04:21.83]漫天黄沙掠过</p>
        <p>[01:11.90][02:35.04][04:23.90]走遍每个角落</p>
        <p>[01:14.05][02:36.99][04:26.20]行走在无尽的苍茫星河</p>
        <p>[01:18.69][02:41.50][04:30.60]白天黑夜交错</p>
        <p>[01:20.80][02:43.56][04:32.65]如此妖娆婀娜</p>
        <p>[01:22.85][02:45.85][04:35.01]蹉跎着岁月又蹉跎了自我</p>
        <p>[01:27.20][02:50.16][04:39.25]前方迷途太多</p>
        <p>[01:29.32][02:52.33][04:41.39]坚持才能洒脱</p>
        <p>[01:31.56][02:54.46][04:43.58]走出黑暗就能逍遥又快活</p>
        <p>[01:38.54]</p>
        <p>[01:49.43]我寻找沙漠绿洲</p>
        <p>[01:51.34]出现海市蜃楼</p>
        <p>[01:53.44]我仿佛看到她在那里等候</p>
        <p>[01:57.80]想起了她的温柔</p>
        <p>[01:59.91]滚烫着我的胸口</p>
        <p>[02:02.19]迷失在昨夜的那壶老酒</p>
        <p>[02:06.42]我穿上大头皮鞋</p>
        <p>[02:08.75]跨过凛冽荒野</p>
        <p>[02:10.75]我仿佛穿越到另一个世界</p>
        <p>[02:15.20]阿拉丁神灯要倾斜</p>
        <p>[02:17.33]天堂地狱已然重叠</p>
        <p>[02:19.51]突然之间飞来一只蝴蝶</p>
        <p>[03:01.04]</p>
        <p>[03:47.15]我已坠入在这神奇的国度</p>
        <p>[03:51.28]驼铃相伴走向圣堂之路</p>
        <p>[03:55.64]原谅我曾经恍惚陷入迷途</p>
        <p>[03:59.80]遮住了眼眸</p>
        <p>[04:01.80]湮没了意图</p>
        <p>[04:04.02]怎能被这样征服</p>
        <p>[04:48.19]梦里回到最初</p>
        <p>[04:50.08]浪潮起起伏伏</p>
        <p>[04:52.29]彷徨着未来又彷徨着孤独</p>
        <p>[04:56.74]漫长人生旅途</p>
        <p>[04:58.87]花开花落无数</p>
        <p>[05:01.03]沸腾的时光怎能被荒芜</p>
        <p>[05:05.76]清晨又到日暮</p>
        <p>[05:07.48]天边飞鸟群逐</p>
        <p>[05:09.79]摇曳着苍穹又描摹着黄土</p>
        <p>[05:14.26]东方鱼肚白出</p>
        <p>[05:16.53]烈日绽放吐露</p>
        <p>[05:18.47]放下尘浮我已踏上归途</p>
    </div>
    <div class="box">
        <div class="cover"></div>
    </div>

    <audio src="展展与罗罗 - 沙漠骆驼.mp3" controls></audio>

 下面是js部分,还要引一下jQuery文件

<script>
        $(function () {
            //  解析歌词文件,分割时间和歌词
            var $p = $(".lrc_content p");
            var audio = document.querySelector('audio');

            // 歌词对象
            var oLrc = {
                ti: "",  //歌名
                ar: "",  //作者
                al: "",  //专辑名
                ms: []   //歌词数组 {t:时间,content:歌词}
            };

            // 解析界面上的lrc数据
            for (var i = 0; i < $p.length; i++) {
                var txt = $p.eq(i).text().trim();
                var subTxt = txt.substring(txt.indexOf("[") + 1, txt.indexOf("]"));
                var subTxtArr = subTxt.split(":");
                if (isNaN(parseInt(subTxtArr[0]))) {
                    oLrc[subTxtArr[0]] = subTxtArr[1];
                } else {
                    var times = txt.match(/\[(\d+:.+?)\]/g); // 匹配字符串中的日期,返回一个数组
                    for (var j = 0; j < times.length; j++) {
                        var one = times[j].substring(1, times[j].indexOf("]")).split(":");
                        oLrc.ms.push({
                            t: (parseInt(one[0]) * 60 + parseFloat(one[1])).toFixed(3),
                            c: txt.substr(txt.lastIndexOf("]") + 1)
                        });
                    }
                }
            }
            oLrc.ms.sort(function (a, b) {
                return a.t - b.t;
            })

            // 把生成的数据显示到界面上去
            var $ul = $("<ul></ul>");
            for (var i = 0; i < oLrc.ms.length; i++) {
                var $li = $("<li></li>").text(oLrc.ms[i].c);
                $ul.append($li);
            }
            $(".cover").append($ul);

            var lineNo = 0; // 当前行歌词
            var preLine = 6; // 当播放6行后开始滚动歌词
            var lineHeight = -30; // 每次滚动的距离

            // 让字幕跟最歌曲播放
            // 歌词高亮  增加类名active
            function highLight() {
                var $li = $("li");
                $li.eq(lineNo).addClass("active").siblings().removeClass("active");
                if (lineNo > preLine) {
                    $ul.stop(true, true).animate({ top: (lineNo - preLine) * lineHeight });
                }
            }

            highLight();

            audio.addEventListener("timeupdate", function () {
                if (lineNo == oLrc.ms.length) return;
                var curT = audio.currentTime;
                var x = getLineNo(curT);
                // if (curT >= parseFloat(oLrc.ms[lineNo].t)) {
                // 因为后退和前进的判断在getlineNo里已经进行了判断,所以这里直接就赋值
                lineNo = x;
                highLight();
                lineNo++;
                // }
            });

            // 当快进或者倒退的时候,找到最近的后面那个oLrc.ms[i].t
            function getLineNo(ct) {
                if (ct >= parseFloat(oLrc.ms[lineNo].t)) {
                    // 快进
                    for (var i = oLrc.ms.length - 1; i >= lineNo; i--) {
                        // 倒着查找比curT时间小的第一个值
                        if (ct >= parseFloat(oLrc.ms[i].t)) {
                            return i;
                        }
                    }
                } else {
                    // 后退
                    for (var i = 0; i <= lineNo; i++) {
                        if (ct <= parseFloat(oLrc.ms[i].t)) {
                            // i-1 不然会导致字幕快一条
                            return i -1 ;
                        }
                    }
                }
            }


            function goBack() {
                lineNo = 0;
                $ul.animate({ top: 0 });
                highLight();
            }
            audio.addEventListener("ended", function () {
                goBack();
            });
        });
    </script>

快进倒退思路:

快进后,我从后往前找,找到一个比当前值(audio提供的一个属性,数值类型)小的,说明我差不多正好快进到了那个位置,然后把对应的下标值返回,这个就是我们需要高亮显示的那一行了,接下来就是自己播放++就行。

倒退后,我从头开始找,找到比当前值大的,说明,我差不多倒退到了那个位置,返回这个下标值-1才行,不然歌词会比音乐快一行,接下来的一样就是自动播放就行。

思路就是这样的,别的说明,可以参考文章开头的博客,一些样式自行修改,可能会有一些bug,欢迎提出来。

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值