audio实现歌词同步

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

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

好的,使用了标签,那么现在我们就要开始导入歌单啦。
因为我想多复习下ajax,所以处理ajax的数据就比较多啦
首先是自动生成歌单,歌单文件名是music.xml内容如下
music.xml文件
然后使用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+"<li id='"+id+"' title='"+title+"' key='no' onclick='ajaxMusic(this)'>"+title+"</li>";
                });
                $("#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,而且要按照歌词文件的一般格式,如
歌词文件内容
然后我用的是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 = "<p style='top:300px';font-size:'150%'>没有找到歌词</p><br/>"; 
                    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;i<lines.length;i++){
                resy[i] = new 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 +"<p style='top:"+top+"px' key='"+i+"'>"+resy[i][1]+"</p><br/>";
                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("<p style='top:"+Ntop+"px' key='"+(j-7)+"'>"+result[j-7][1]+"</p><br/>");
                        }
                        $("#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.currentTime<currenttime){
                    if(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这个全局变量来记录当前播发的时间,这样可以判断你是否是快退,快进还是切歌。怎么样是不是很简单呢?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值