首先看下效果:html5带歌词同步的音乐播放器
下面是播放器js代码:
//获取歌曲链接并插入dom中
var myAudio = null;
var control = null;
var prevSongBtn = null;
var nextSongBtn = null;
var loadingBar = null;
var playList = ['https://5.jimth.com/view/demomusic/niliuchenghe.mp3','https://5.jimth.com/view/demomusic/xiaopingguo.mp3'];
var lrcList = ['https://5.jimth.com/view/demomusic/niliuchenghe.txt','https://5.jimth.com/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;
}
