首先看下效果:html5带歌词同步的音乐播放器
下面是播放器js代码:
//获取歌曲链接并插入dom中 var myAudio = null; var control = null; var prevSongBtn = null; var nextSongBtn = null; var loadingBar = null; var playList = ['http://www.5imoban.net/view/demomusic/niliuchenghe.mp3','http://www.5imoban.net/view/demomusic/xiaopingguo.mp3']; var lrcList = ['http://www.5imoban.net/view/demomusic/niliuchenghe.txt','http://www.5imoban.net/view/demomusic/xiaopingguo.txt']; var nowIdx = 0; var drag = null; var speed = null; var lrcArr = []; //保存歌词 var timestamp = []; //保存时间戳 var lrcArea = ''; var timer1 = null; var timer2 = null; var timer3 = null; initPlayer(); function initPlayer(){ loadingBar = document.querySelector('#loading'); myAudio = document.getElementById("audio"); control = document.querySelector('#control'); drag = document.getElementById("drag"); speed = document.getElementById("speed"); lrcArea = document.getElementById('lrc'); prevSongBtn = document.querySelector('#prevSong'); nextSongBtn = document.querySelector('#nextSong'); prevSongBtn.addEventListener('touchend',prevEv, false); nextSongBtn.addEventListener('touchend',nextEv, false); playSong(0); } //获取歌曲链接并插入dom中 function playSong(idx){ clearInterval(timer1); clearInterval(timer2); clearInterval(timer3); loadingBar.style.display = 'block'; myAudio.src = playList[idx]; //myAudio.loop = true; playCotrol(); //播放控制函数 //歌词 lrcArr = []; timestamp = []; lrcArea.innerHTML = ''; handleLrc(idx); } //点击播放/暂停 function clicks() { control.removeEventListener('click',controlEv, false); control.addEventListener('click',controlEv, false); } function controlEv(){ if (control.classList.contains("play")) { control.classList.add("pause"); control.classList.remove("play"); myAudio.play();//开始播放 dragMove();//并且滚动条开始滑动 } else { control.classList.remove("pause"); control.classList.add("play"); myAudio.pause(); } } //播放时间 function timeChange(time, timePlace) {//默认获取的时间是时间戳改成我们常见的时间格式 var timePlace = document.getElementById(timePlace); //分钟 var minute = time / 60; var minutes = parseInt(minute); if (minutes < 10) { minutes = "0" + minutes; } //秒 var second = time % 60; seconds = parseInt(second); if (seconds < 10) { seconds = "0" + seconds; } var allTime = "" + minutes + "" + ":" + "" + seconds + "" timePlace.innerHTML = allTime; } //播放事件监听 function playCotrol() { //歌曲一经完整的加载完毕 myAudio.addEventListener("loadeddata",loadeddataEv, false); //暂停 myAudio.addEventListener("pause",pauseEv, false); //播放 myAudio.addEventListener("play",playEv, false); myAudio.addEventListener("ended",endEv, false); } //加载完成播放事件 function loadeddataEv(){ loadingBar.style.display = 'none'; control.classList.add("play"); control.classList.remove("pause"); addListenTouch(); //歌曲加载之后才可以拖动进度条 var allTime = myAudio.duration; timeChange(allTime,'endTime'); setStartTime(); clicks(); lrcSync(); } //时间跳动 function setStartTime(){ clearInterval(timer1); timer1 = setInterval(function() { var currentTime = myAudio.currentTime; timeChange(currentTime, "startTime"); }, 1000); } function pauseEv() { //监听暂停 control.classList.add("play"); control.classList.remove("pause"); if (myAudio.currentTime == myAudio.duration) { myAudio.pause(); myAudio.currentTime = 0; } clearInterval(timer1); clearInterval(timer2); clearInterval(timer3); } function playEv(){ control.classList.add("pause"); control.classList.remove("play"); dragMove(); setStartTime(); lrcSync(); } function endEv(){ nextEv(); } //进度条 var startX, x, aboveX = 0; //拖动监听touch事件 function addListenTouch() { drag.addEventListener("touchstart", touchStart, false); drag.addEventListener("touchmove", touchMove, false); drag.addEventListener("touchend", touchEnd, false); } //touchstart,touchmove,touchend事件函数 function touchStart(e) { var touch = e.touches[0]; startX = touch.pageX; } function touchMove(e) { var touch = e.touches[0]; x = touch.pageX - startX; //滑动的距离 drag.style.left = aboveX + x + "px"; // speed.style.left = -((window.innerWidth) - (aboveX + x)) + "px"; } function touchEnd(e) { //手指离开屏幕 e.preventDefault(); aboveX = parseInt(drag.style.left); var touch = e.touches[0]; var dragPaddingLeft = drag.style.left; var change = dragPaddingLeft.replace("px", ""); numDragpaddingLeft = parseInt(change); var currentTime = (numDragpaddingLeft / (window.innerWidth - 30)) * myAudio.duration;//30是拖动圆圈的长度,减掉是为了让歌曲结束的时候不会跑到window以外 myAudio.currentTime = currentTime; } //拖动的滑动条前进 function dragMove() { clearInterval(timer3); timer3 = setInterval(function() { drag.style.left = (myAudio.currentTime / myAudio.duration) * (window.innerWidth - 30 - 30) + "px"; speed.style.left = -((window.innerWidth-30) - (myAudio.currentTime / myAudio.duration) * (window.innerWidth - 30 - 30)) + "px"; }, 500); } //上一首 function prevEv(){ nowIdx--; if(nowIdx < 0){ nowIdx=0; } playSong(nowIdx); } //下一首 function nextEv(){ nowIdx++; if(nowIdx > (playList.length-1)){ nowIdx=playList.length-1; } playSong(nowIdx); } //处理lrc function handleLrc(idx){ var xhr = new XMLHttpRequest(); xhr.open('GET',lrcList[idx], false); xhr.send(null); if (xhr.readyState == 4 && xhr.status == 200) { var lrc = xhr.responseText; var re = /(\[.+\])(.+)?/gm, tmpArr, i, len; var txt = lrc.replace(re,function(a, b, c) { return b + (c === undefined ? ' ': c) + '\n'; }); tmpArr = txt.split('\n'); //去除空白歌词 for (i = 0, len = tmpArr.length; i < len; i++) { var item = trim(tmpArr[i]); if (item.length > 0) { lrcArr.push(item); } } var _html = ''; for (i = 0; i < lrcArr.length; i++) { if (i === 0) { _html += '<li class="on">'; }else if(i === 1 || i === 2){ _html += '<li>'; }else{ _html += '<li class="hidden">'; } _html += lrcArr[i].replace(/\[.+\]/i, ''); _html += '</li>'; //处理时间 timestamp.push(lrcArr[i].replace(re,function(a, b, c) { return b; }).replace('[', '').replace(']', '')); } lrcArea.innerHTML = _html; } } //歌词同步 function lrcSync(){ clearInterval(timer2); timer2 = setInterval(function() { var curTime = myAudio.currentTime; for (var i = 0, len = timestamp.length - 1; i < len; i++) { var prevTime = formatTimeStamp(timestamp[i]), nextTime = formatTimeStamp(timestamp[i + 1]); //当前播放时间与前后歌词时间比较,如果位于这两者之间则转到该歌词 if (parseFloat(curTime) > prevTime && parseFloat(curTime) < nextTime) { var allLines = document.querySelectorAll('#lrc li'); for(var j=0; j<allLines.length; j++){ allLines[j].classList.add('hidden'); allLines[j].classList.remove('on'); } try{ allLines[i+1].classList.add('on'); allLines[i+1].classList.remove('hidden'); allLines[i].classList.remove('hidden'); allLines[i+2].classList.remove('hidden'); }catch(e){} break; } } },300); } function trim(str) { return str.replace(/(^\s*)|(\s*$)/g, ""); } function formatTimeStamp(timestamp) { var re = /([0-9]+):([0-9]+)\.([0-9]+)/i, seconds = timestamp.replace(re, function(a, b, c, d) { return Number(b * 60) + Number(c) + parseFloat('0.' + d); }); return seconds; }