前几天才刚开始接触HTML5和CSS3。学习了一下里面的一些炫酷的新特性。不过,对于原生的HTML5的媒体播放器,真的不得不吐槽:就三个按钮 界面还那么丑。所以觉得自己整一个好看的播放器。老话说:说不如干,纸上谈兵终觉浅。所以结合这几天来学的东西,自己写了一个HTML5的播放器。
HTML5原生播放器:
我们的效果图:
歌曲列表:
首先分析下界面,将主面板解剖一下:
整个界面都是用Html5的Canvas绘制的,切换歌曲的时候,中间的歌曲名和后面的专辑封面也会动态切换。默认顺序循环播放,就是一首接下一首,也可以切换成随机播放。
最上边的按钮是切换到歌曲列表面板;
中间的一排按钮,最左边的是顺序播放;
第二个是上一首;第三个是暂停/播放;
第四个是下一首;第五个是随机播放。
下面的是音量条,拖动控制音量;
最下面是歌词面板,点击后显示歌词。
最外边有一圈蓝色的进度条,提示歌曲当前播放进度。
代码实现:
主要的html5代码:
<!--Music Box-->
<div id="musicbox">
<div id="container">
<label class="to-back-label" for="to-back"><i class="fa fa-bars fa-lg"></i></label>
<input type="checkbox" id="to-back"><!-- playlist toggle -->
<canvas id="progress" width="320" height="320"></canvas><!-- progress bar -->
<div id="player">
<audio id="audio" controls>
</audio>
<img id="imcover" src="images/music/回梦游仙.png"><!-- album cover -->
<label class="to-lyrics-label" for="to-lyrics"><i class="fa fa-caret-down fa-lg"></i></label>
<input type="checkbox" id="to-lyrics"><!-- lyrics toggle -->
<div class="cover">
<div class="controls">
<div id="currentM" >正在播放:<strong id="rmusic">回梦游仙</strong></div>
<button id="randoms" title="随机播放"><i class="fa fa-retweet fa-lg"></i></button>
<button id="backward" title="上一首"><i class="fa fa-backward fa-2x"></i></button>
<button id="play-pause" title="Play" onclick="togglePlayPause()"><i class="fa fa-play fa-3x"></i></button>
<button id="forward" title="下一首"><i class="fa fa-forward fa-2x"></i></button>
<button id="sequence" title="顺序播放"><i class="fa fa-random fa-lg"></i></button>
<input id="volume" name="volume" min="0" max="1" step="0.1" type="range" onchange="setVolume()" />
</div><!-- #controls -->
<!-- <div class="info"> <p class="song"><a href="#" target="_blank">Abitude</a></p> <p class="author"><a href="#" target="_blank">Abi</a></p> </div><!-- #info -->
<div id="lycs" class="lyrics">
<p>仙剑奇侠传4——回梦游仙.</p>
<p> 冰封的泪 如流星陨落</p>
<p> 跌碎了谁的思念</p>
<p> 轮回之间 前尘已湮灭</p>
<p> 梦中模糊容颜</p>
<p> 昆仑巅 江湖远 花谢花开花满天</p>
<p>叹红尘 落朱颜 天上人间</p>
<p>情如风 情如烟 琵琶一曲已千年</p>
<p>今生缘 来生缘 沧海桑田</p>
<p>成流年</p>
<p>古老的剑 斩断了宿怨</p>
<p>唤醒了谁的誓言</p>
<p>转瞬之间 隔世的爱恋</p>
<p>追忆往日缱绻</p>
<p>昆仑巅 浮生远 梦中只为你流连</p>
<p>笑红尘 画朱颜 浮云翩跹</p>
<p>情难却 情相牵 只羡鸳鸯不羡仙</p>
<p>今生缘 来生缘 难分难解</p>
<p>昆仑巅 浮生远 梦中只为你流连</p>
<p> 笑红尘 画朱颜 浮云翩跹</p>
<p> 情难却 情相牵 只羡鸳鸯不羡仙</p>
<p> 今生恋 来生恋 莫让缠绵 成离别</p>
</div><!-- #lyrics -->
<p class="scroll">scroll down</p>
</div><!-- #cover -->
</div><!-- #player -->
<div id="flip-back">
<ol class="playlist" id="playlist">
</ol>
</div><!-- #flip-back -->
</div><!-- #container -->
</div>
<script type="text/javascript" src="js/musicbox.js"></script>
musicbox.js中的代码:
$(function() {
// 播放器
var Player;
Player = {
// 歌曲路径
path: 'video/',
imgPath:'images/music/',
// 歌曲数据
data: null,
imgs: null,
// 当前播放歌曲的 索引
currentIndex: -1,
// 播放器元素jquery对象
$audio: $('#audio'),
// 歌曲列表
$mList: $('#playlist'),
//正在播放的歌曲
$rmusic: $('#rmusic'),
$cover: $('#imcover'),
// 初始化 数据
init: function () {
// 数据一般来自服务器端,通过ajax 加载数据,这里是模拟
//歌曲的数据
Player.data = ['GlassySky.mp3', '回梦游仙.mp3', 'unravel.mp3','一直很安静.mp3'];
//封面的数据
Player.imgs = ['GlassySky.jpg', '回梦游仙.png', 'unravel.jpg','一直很安静.png'];
Player.$rmusic.html(Player.data[Player.currentIndex]);
//初始化
var mhtml = '';
var len = Player.data.length;
//初始化歌曲列表
for (var i = 0; i < len; i++) {
mhtml += '<li value="' + i + '"><a >' + Player.data[i] + '</a></li>';
}
Player.$mList.html(mhtml);
//初始化专辑封面
Player.$cover.attr("src", Player.imgPath+Player.imgs[0]);
},
// 就绪
ready: function () {
// 控制
Player.audio = Player.$audio.get(0);
Player.$rmusic.html(Player.data[Player.currentIndex]);
// 播放
$('#btn-play').click(function () {
Player.audio.play();
if (Player.currentIndex == -1) {
$('#btn-next').click();
}
});
// 暂停
$('#btn-pause').click(function () {
Player.audio.pause();
});
// 下一曲
$("#forward").click(function () {
if (Player.currentIndex == -1) {
Player.currentIndex = 0;
} else if (Player.currentIndex == (Player.data.length - 1)) {
Player.currentIndex = 0;
} else {
Player.currentIndex++;
}
var currentMusic=Player.data[Player.currentIndex];
currentMusic = currentMusic.substring(0,currentMusic.indexOf('.'));
console.log("Player.currentIndex : " + Player.currentIndex);
Player.audio.src = Player.path + Player.data[Player.currentIndex];
Player.$rmusic.html(currentMusic);
Player.$cover.attr("src", Player.imgPath+Player.imgs[Player.currentIndex]);
Player.audio.play();
});
// 上一曲
$('#backward').click(function () {
if (Player.currentIndex == -1) {
Player.currentIndex = 0;
} else if (Player.currentIndex == 0) {
Player.currentIndex = (Player.data.length - 1);
} else {
Player.currentIndex--;
}
var currentMusic=Player.data[Player.currentIndex];
currentMusic = currentMusic.substring(0,currentMusic.indexOf('.'));
Player.audio.src = Player.path + Player.data[Player.currentIndex];
Player.$cover.attr("src", Player.imgPath+Player.imgs[Player.currentIndex]);
Player.$rmusic.html(currentMusic);
Player.audio.play();
});
// 单曲循环
$('#btn-loop').click(function () {
console.log("Player.currentIndex :", Player.currentIndex);
Player.audio.onended = function () {
Player.audio.load();
Player.audio.play();
};
});
// 顺序播放
$('#sequence').click(function () {
console.log("Player.currentIndex :", Player.currentIndex);
Player.audio.onended = function () {
$('#btn-next').click();
};
});
// 随机播放
$('#randoms').click(function () {
Player.audio.onended = function () {
var i = parseInt((Player.data.length - 1) * Math.random());
alert(i);
playByMe(i);
};
});
// 播放指定歌曲
function playByMe(i) {
i=parseInt(i);
Player.audio.src = Player.path + Player.data[i];
Player.audio.play();
Player.currentIndex = i;
Player.$rmusic.html(Player.data[Player.currentIndex]);
Player.$cover.attr("src", Player.imgPath+Player.imgs[Player.currentIndex]);
}
// 歌曲被点击
$('#playlist li').click(function () {
$(this).find('a').find('i').remove();
$(this).find('a').css("color","#26C5CB");
$(this).find('a').prepend("<i class=\"fa fa-play\" style=\"margin-right:4px;\"></i>");
$(this).siblings().find('a').css("color","#ffffff");
$(this).siblings().find('a').find('i').remove();
var i = parseInt($(this).attr('value'));
playByMe(i);
/*style="color:#26C5CB;"*/
});
},
//循环播放
loop:function(){
Player.audio.onended = function(){
if (Player.currentIndex == -1) {
Player.currentIndex = 0;
} else if (Player.currentIndex == (Player.data.length - 1)) {
Player.currentIndex = 0;
} else {
Player.currentIndex++;
}
var currentMusic=Player.data[Player.currentIndex];
currentMusic = currentMusic.substring(0,currentMusic.indexOf('.'));
console.log("Player.currentIndex : " + Player.currentIndex);
Player.audio.src = Player.path + Player.data[Player.currentIndex];
Player.$cover.attr("src", Player.imgPath+Player.imgs[Player.currentIndex]);
Player.$rmusic.html(currentMusic);
Player.audio.play();
}
}
};
Player.init();
Player.ready();
Player.loop();
});
audio.controls = false;
audio.addEventListener('timeupdate', function() {
updateProgress();
}, false);
function togglePlayPause() {
if (audio.paused || audio.ended) {
playpause.title = "Pause";
playpause.innerHTML = '<i class="fa fa-pause fa-3x"></i>';
audio.play();
} else {
playpause.title = "Play";
playpause.innerHTML = '<i class="fa fa-play fa-3x"></i>';
audio.pause();
}
}
function setVolume() {
audio.volume = volume.value;
}
//更新进度条
function updateProgress() {
var percent = Math.floor((100 / audio.duration) * audio.currentTime);
progress.value = percent;
var canvas = document.getElementById('progress');
var context = canvas.getContext('2d');
var centerX = canvas.width / 2;
var centerY = canvas.height / 2;
var radius = 150;
var circ = Math.PI * 2;
var quart = Math.PI / 2;
var cpercent = percent / 100; /* current percent */
context.beginPath();
context.arc(centerX, centerY, radius, 0, ((circ) * cpercent), false);
context.lineWidth = 10;
context.strokeStyle = '#26C5CB';
context.stroke();
if (audio.ended) resetPlayer();
}
//重置播放器
function resetPlayer() {
audio.currentTime = 0; context.clearRect(0,0,canvas.width,canvas.height);
playpause.title = "Play";
playpause.innerHTML = '<i class="fa fa-play fa-3x"></i>';
}
由于时间关系,所以歌词列表的动态显示功能还没做。这需要解析歌词的格式。准备在下次完成歌词列表功能。