audio实现歌词同步

网上已经可以找到和歌词同步的不少方法,但是刚刚接触H5的小白,也想写上一些自己歌词同步时一些想法。我由于只考虑前端,所以就没有涉及服务器的问题了,浏览器本身请求本地文件比较严格,会出现如下错误
这里写图片描述
所以你就需要修改浏览器的相关配置,这里奉上链接
http://www.w3dev.cn/article/20141031/file-protocol-config-chrome-support-ajax-request.aspx
首先呢,我先附上自己做的网站,因为自己比较喜欢看霹雳布袋戏,所以我就用霹雳布袋戏的歌曲测试啦(哈哈,扯远啦),附上图
audio实现歌词同步_第1张图片
audio实现歌词同步_第2张图片
好的,看完了效果图,哈,知道自己做的水水的,不喜勿喷。
那么首先我们就是要先使用标签

<audio id="musicAudio" controls="controls" style="width:800px;" class="audioCss">
            你的浏览器不兼容.
    audio>

好的,使用了标签,那么现在我们就要开始导入歌单啦。
因为我想多复习下ajax,所以处理ajax的数据就比较多啦
首先是自动生成歌单,歌单文件名是music.xml内容如下
audio实现歌词同步_第3张图片
然后使用ajax处理数据,并且在网页上面生成歌单,同时给每个li加上点击事件,代码如下

$.ajax({
            type:"GET",
            url:"order/music.xml",
            success: function(order){
                var li = "";
                $(order).find("music").each(function(){
                    var title = $(this).find("title").text();
                    var id    = $(this).find("author").text();
                    li=li+"
  • "+title+"
  • "
    ; }); $("#musicOl").append(li); $("#musicOl li").each(function(){ $(this).mousemove(function(e){ if($(this).attr("key")!='yes') $(this).css("color","black"); }); $(this).mouseout(function(e){ if($(this).attr("key")!='yes') $(this).css("color","white"); }); }); } });

    值得一提的是mousemove和mouseout是我为了添加特效,所以才加上去的,不需要可以不用,还有就是我请求的文件是本地文件,编辑工具是sublime Text3。
    然后就是获得歌词,这里的歌词文件是xx.lrc,而且要按照歌词文件的一般格式,如
    audio实现歌词同步_第4张图片
    然后我用的是javascript的ajax,代码如下

    function ajaxMusic(obj){
            $("li[id][key$='yes']").css("color","white").attr("key","no");
            $("#"+obj.id).attr("key","yes").css("color","red");
            var audio = document.getElementById("musicAudio");
            audio.pause();
            var xmlhttp;
            if(window.XMLHttpRequest){
                xmlhttp = new XMLHttpRequest();
            }
            else{
                xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
            }
            xmlhttp.onreadystatechange=function(){
                if(xmlhttp.readyState==4 && xmlhttp.status==0){
                    audio.src = "music/"+obj.title+".mp3";
                    audio.play();
                    if(xmlhttp.responseText==''){
                        document.getElementById("musicText").innerHTML = "

    没有找到歌词


    "
    ; musicT.splice(0,musicT.length-1); } else{ xmltext = xmlhttp.responseText; musicT = parseLyric(xmlhttp.responseText); parseStart(musicT); musicLrc(musicT); } } } xmlhttp.open("GET","lrc/"+obj.id+".lrc",true); xmlhttp.send(); }

    好的,我来解释一下其中
    ("li[id][key =’yes’]”).css(“color”,”white”).attr(“key”,”no”);
    $(“#”+obj.id).attr(“key”,”yes”).css(“color”,”red”);
    也是为了标注选择的歌曲目标特效罢了,可以不加。
    对了,再说明一下,当javascript请求本地文件的时候,如果成功,xmlhttp.status = =0
    还有尽管你没有找到该文件名,浏览器会这样的错误
    文件找不到所报的异常
    不过这没有关系啦,对于前端你无法知道服务器的东西,可是值得一提的是,由于没有找到文件,所以xmlhttp.responseText得到的值是”(空格)”,即xmlhttp.responseText==“(空格)”然后我们就可以根据空格来判断是否有歌词。
    好的,然后你得到了歌词,那么你就必须对他进行处理,由于我是小白,所以想到的就是存储在二维数组上,代码和方法名如下:

    function parseLyric(txt){
                var lines = txt.split("\n");
                var resy = new Array();
                var j = lines.length-1;
                for(var i=0;inew Array();
                    var line = lines[j].split("]");
                    var Tm   = line[0].substring(1,line[0].length).split(":");
                    resy[i][0] = parseInt(Tm[0],10)*60+parseFloat(Tm[1]);
                    resy[i][1] = line[1];
                    j--;
                }
                return resy;
            }

    好的,当然啦,歌曲在没有播放前,总是要有一些歌词先显示出来,所以这里我就先截取前七行歌词,代码如下

    function parseStart(resy){
                var res = "";
                var left=200,top=300;
                var i = resy.length-1;
                for(var j=0;j<7;j++){
                    res = res +"

    "+resy[i][1]+"


    "
    ; top=top+40; i--; } document.getElementById("musicText").innerHTML=res; return res; }

    其中top指的是离包含DIV的高度,之后就是重头戏,,你得到了处理后歌词数组,然后你就要与播放的歌曲同步,同步的方法就是根据歌次文件前面的时间与播放的当前时间做对比,代码如下

    function musicLrc(result){
                var audioEvent = document.getElementById("musicAudio");
                var resText=document.getElementById("musicText");
                var j =result.length-1,n = result.length-1;
                var top = 300,isback = false;
                var backtop = 300;
                audioEvent.ontimeupdate =function(e){
                    if(result.length!=0){
                        console.log("result="+result[j][0]);
                        if(this.currentTime>result[j][0]){
                            currenttime=this.currentTime;
    
                            var ltop = $("#musicText p").last().css("top").split("px");
                            var Ntop = parseInt(ltop[0])+40;
                            if(j>=7&&j-7>=0){
                                $("#musicText").append("

    "+result[j-7][1]+"


    "
    ); } $("#musicText p").each(function(){ var lineTop=$(this).css("top").split("px"); $(this).css("top",(lineTop[0]-40)+"px"); $(this).css("color","black").css("font-size","200%"); if($(this).attr("key")==j){ $(this).css("color","red").css("font-size","300%"); } }); j=j-1; } else { if(this.currentTimeif(this.currentTime>1){ j++; $("#musicText p").each(function(){ var lineTop=$(this).css("top").split("px"); $(this).css("top",(parseInt(lineTop[0])+40)+"px"); $(this).css("color","black").css("font-size","200%"); if($(this).attr("key")==j){ $(this).css("color","red").css("font-size","300%"); } }); } } } } }; return ; }

    只需要和歌词进行对比,判断是否大于和小于,这样就可以实现快进和快退啦,还有值得一提的是我使用了currenttime这个全局变量来记录当前播发的时间,这样可以判断你是否是快退,快进还是切歌。怎么样是不是很简单呢?

    你可能感兴趣的:(前端,audio,前端)