JS实现歌词同步滚动效果

实现歌词同步滚动效果,首先要用audio标签引入音频

<div id="h_center1">
        <span>当前播放:</span>
        <span>大鱼海棠</span>
        <audio id="now_music" src="双笙 - 大鱼.mp3"></audio>
        <img src="picture/former.jpg"/>
        <img src="picture/stop.jpg" class="clickToStop" width="21" height="58"/>
        <img src="picture/next.jpg"/>
    </div>

并且也要将歌词文件写入textarea 文本域内并隐藏,然后在获取歌词时放入指定位置

<textarea id="lrc_content" name="textfield" cols="70" rows="10" style="display:none;">
        [ti:大鱼]
        [ar:王若伊]
        [al:大鱼]
        [ly:尹约]
        [mu:钱雷]
        [ma:]
        [pu:]
        [by:ttpod]
        [total:278752]
        [offset:0]
        [00:00.410]大鱼 - 王若伊
        [00:01.410]作词:尹约
        [00:02.310]作曲:钱雷
        [00:03.161]
        [00:44.447]海浪无声将夜幕深深淹没
        [00:51.200]漫过天空尽头的角落
        [00:57.995]大鱼在梦境的缝隙里游过
        [01:04.848]凝望你沉睡的轮廓
        [01:10.898]看海天一色 听风起雨落
        [01:17.705]执子手吹散苍茫茫烟波
        [01:24.506]大鱼的翅膀 已经太辽阔
        [01:32.112]我松开时间的绳索
        [01:38.017]怕你飞远去
        [01:41.620]怕你离我而去
        [01:45.173]更怕你永远停留在这里
        [01:51.876]每一滴泪水
        [01:55.428]都向你流淌去
        [01:59.623]倒流进天空的海底
        [02:05.201]
        [02:20.568]海浪无声将夜幕深深淹没
        [02:27.118]漫过天空尽头的角落
        [02:34.029]大鱼在梦境的缝隙里游过
        [02:40.733]凝望你沉睡的轮廓
        [02:47.051]看海天一色 听风起雨落
        [02:53.654]执子手吹散苍茫茫烟波
        [03:00.637]大鱼的翅膀 已经太辽阔
        [03:08.087]我松开时间的绳索
        [03:14.187]看你飞远去 看你离我而去
        [03:21.039]原来你生来就属于天际
        [03:27.889]每一滴泪水 都向你流淌去
        [03:35.540]倒流回最初的相遇
    </textarea>

    <ul id="text" style="overflow: hidden;">

    </ul>
JS实现

首先要把获取到的歌词解析为对象数组,并且放入指定位置,并且溢出隐藏
(t.split(“:”)[0] * 60 + parseFloat(t.split(“:”)[1])).toFixed(3)这里是要把原来的mm:ss的时间格式改为秒

var medisArray = new Array();   // 定义一个新的数组
function createLrc () {
  var medis = document.getElementById('lrc_content').innerText;
  var medises = medis.split("\n");    // 用换行符拆分获取到的歌词

  $.each(medises, function (i, item) {    // 遍历medises,并且将时间和文字拆分开,并push进自己定义的数组,形成一个对象数组
    var t = item.substring(item.indexOf("[") + 1, item.indexOf("]"));
    medisArray.push({

      t: (t.split(":")[0] * 60 + parseFloat(t.split(":")[1])).toFixed(3),
      c: item.substring(item.indexOf("]") + 1, item.length)
    });
  });
  var ul = $("#text");
  // 遍历medisArray,并且生成li标签,将数组内的文字放入li标签
  $.each(medisArray, function (i, item) {
    var li = $("<li style='list-style: none;'>");
    li.html(item.c);
    ul.append(li);
  });
}
createLrc();

实现文字高亮滚动

var fraction = 0.5;
var topNum = 0;
function lineHeight(lineno){
  var ul = $("#text");
  var $ul = document.getElementById('text');
 // 令正在唱的那一行高亮显示
  if (lineno > 0) {
    $(ul.find("li").get(topNum + lineno - 1)).removeClass("lineheight");
  }
  var nowline = ul.find("li").get(topNum + lineno);
  $(nowline).addClass("lineheight");

    // 实现文字滚动
  var _scrollTop;
  $ul.scrollTop = 0;
  if ($ul.clientHeight * fraction > nowline.offsetTop) {
    _scrollTop = 0;
  } else if (nowline.offsetTop > ($ul.scrollHeight - $ul.clientHeight * (1 - fraction))) {
    _scrollTop = $ul.scrollHeight - $ul.clientHeight;
  } else {
    _scrollTop = nowline.offsetTop - $ul.clientHeight * fraction;
  }

  //以下声明歌词高亮行固定的基准线位置成为 “A”
  if ((nowline.offsetTop - $ul.scrollTop) >= $ul.clientHeight * fraction) {
    //如果高亮显示的歌词在A下面,那就将滚动条向下滚动,滚动距离为 当前高亮行距离顶部的距离-滚动条已经卷起的高度-A到可视窗口的距离
    $ul.scrollTop += Math.ceil(nowline.offsetTop - $ul.scrollTop - $ul.clientHeight * fraction);

  } else if ((nowline.offsetTop - $ul.scrollTop) < $ul.clientHeight * fraction && _scrollTop != 0) {
    //如果高亮显示的歌词在A上面,那就将滚动条向上滚动,滚动距离为 A到可视窗口的距离-当前高亮行距离顶部的距离-滚动条已经卷起的高度
    $ul.scrollTop -= Math.ceil($ul.clientHeight * fraction - (nowline.offsetTop - $ul.scrollTop));

  } else if (_scrollTop == 0) {
    $ul.scrollTop = 0;
  } else {
    $ul.scrollTop += $(ul.find('li').get(0)).height();
  }
}

监听audiotimeupdate 事件,实现文字与音频的同步
如果medisArray[lineNo].t <=T && T<= medisArray[lineNo + 1].t,那么行号为lineNo的这行歌词就需要高亮

var lineNo = 10;
audio.ontimeupdate = function () {
  if (lineNo == medisArray.length - 1 && audio.currentTime.toFixed(3) >= parseFloat(medisArray[lineNo].t)) {
    lineHeight(lineNo);
  }
  if (parseFloat(medisArray[lineNo].t) <= audio.currentTime.toFixed(3) &&
    audio.currentTime.toFixed(3) <= parseFloat(medisArray[lineNo + 1].t)) {
    lineHeight(lineNo);
    lineNo++;
  }
};
  • 20
    点赞
  • 98
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值