html5 audio實現歌詞同步
阿新 • • 發佈:2019-02-17
audio標籤用於播放音訊檔案,很不幸,歌詞檔案並沒有相應介面
addTextTrack() 向音訊新增新的文字軌道。//各大瀏覽器都沒有支援
有兩種方法可以實現歌詞同步:
1. 使用setInterval();
2. 監聽timeupdate
兩種方法,個人覺得都不是很完美,暫時找不到更好的方法
function media(dom,src){
this.dom = dom;
this.src = src;
this.audio = this.dom.getElementsByTagName('audio')[0];
this.control = $(this.dom).find(".control" )[0];
this.lyrbox = $(this.dom).find(".lyrics")[0];
this.timer = this.dom.getElementsByTagName('span')[0];
this.timepoint = $(this.dom).find(".time-point")[0];
this.timebardiv = $(this.dom).find('.time-bar div')[0];
this.formatlyr = [];
this.intval = null;
this.init();
formattime = function (t){
var min = parseInt(t/60);
var ss = parseInt(t)%60 ;
ss = ss>9?ss:"0"+ss;
return min+":"+ss;
}
}
media.prototype.init = function() {
var self = this;
self.dom.style["background"] = "url("+self.src.img+") no-repeat";
self.dom.style["background-size"] = "100% 100%" ;
self.audio.src = self.src.mp3;
self.audio.autoplay = true;
self.lyr();
self.audio.addEventListener("canplay",function(){
self.timer.innerHTML = formattime(0)+ "/"+ formattime(self.audio.duration) ;
self.control.style.display="block";
// self.control.style["transition"]="all 4s;"
// self.audio.autoplay = true;
self.audio.play();
if(self.intval) self.intval = null;
self.intval = setInterval(function(){
var len = self.formatlyr.length;
var _c = self.audio.currentTime;
var p =$(self.lyrbox).find('p')
for(var i=0;i<p.length;i++){
if(p[i].style['color'] != ''){
p[i].style['color'] = '';
break;
}
}
for(var i=0;i<len;i++){
var _t = i?self.formatlyr[i-1][0]:0;
var _t1 =i<len-1? self.formatlyr[i+1][0] :9999;
if(_c >= _t && _c < _t1){
self.lyrbox.getElementsByTagName('p')[i].style['color'] = "#1D94E1";
$(self.lyrbox).css("transform","translateY(-"+(i?i-1:0)*32+"px)").css("transition-duration","0.5s");
break;
}
}
var a=_c/self.audio.duration * (self.timebardiv.clientWidth - self.timepoint.clientWidth) ;
$(self.timepoint).css("transform","translateX("+parseInt(a) +"px)");
self.timer.innerHTML = formattime(self.audio.currentTime)+ "/"+ formattime(self.audio.duration) ;
},1000) ;
});
self.ctrltime();
self.togglepause();
self.audio.canplay = function(){
alert('canplay');
}
};
media.prototype.togglepause = function() {
var self = this;
$(".ctrl-pause ").on('click',function(){
$this = $(this).find('a');
if($this.hasClass("play")){
$this.addClass("pause");
$this.removeClass("play");
self.audio.pause();
}else if($this.hasClass("pause")){
$this.removeClass("pause");
$this.addClass("play");
self.audio.play();
}else{
}
});
};
media.prototype.lyr = function() {
var self = this;
function parselyr(d){
var lines = d.split("\n"),pattern=/\[\d{2}:\d{2}.\d{2}\]/g,_l=[];
var fg = document.createDocumentFragment();
lines.forEach(function(i){
if(i.match(pattern)){
_l.push(i);
}
});
_l.forEach(function(i,index){
var s1 = i.split(']'),s2 = s1[0].slice(1),s3 = s2.split(':');
var second = parseInt(s3[0])*60 + parseFloat(s3[1]);
var p = document.createElement('p');
p.innerHTML = s1[1];
fg.appendChild(p);
self.formatlyr.push([second,s1[1]]);
});
self.lyrbox.appendChild(fg);
}
$.get(this.src.lyrics,function(data){
parselyr(data);
});
};
media.prototype.ctrltime = function() {
// body...
var self =this;
self.timebardiv.addEventListener('click',function(e){
var dx = e.pageX - this.offsetLeft;
var ct= parseInt(self.audio.duration*dx/this.clientWidth);
self.audio.currentTime = ct;
},false);
};
$(document).ready(function(){
var m = new media(document.getElementById('playerbox'),sources[0]);
});
只在firefox chorme&& android測試
注意理解canplay事件,這個事件可能會多次觸發。例如當你設定currentTime的時候,
也會觸發canplay事件,這個不好解釋 :(
第二種方法也差不多。