HTML5音乐播放器
2011-04-15 00:00 Feather 阅读(661) 评论(0) 收藏 举报前几天都在研究HTML5的媒体标签Audio和Video,本来打算写写笔记的,但把文章提纲列了出来后,又觉得如果展开来写的话内容实在太多了,于是,还是觉得编写一个Demo好了。
还是先上Demo,还是那句话,请使用Chrome浏览,Safari也可以。刚刚发现iphone也可以完美支持。
基本思路
这个播放器构思了两天,很多细节一直确定不了,很多想法都是Coding的时候爆发出来,然后临时加上去的,虽然是这样,但程序都写得很顺利,没有被什么问题卡住,整个播放器用了半个下午和半个晚上搞定。
目前播放器还很简陋,用户需要听音乐可以直接在输入框中写入歌曲,或者歌手,专辑之类的都可以。点击“我要听这首”,浏览器会发请求到服务器端,服务器到Soso音乐里面抓取,抓取的信息包括歌名,歌手,专辑,以及两个MP3地址。数据交给前端后,就自由发挥了。
一开始的想法是音乐控制栏也自己弄的,这样可以在各个浏览器中统一样式,而且控制可以更加灵活。但是,我最终还是用了默认的控制栏,主要原因还是工程量太大了,换句话说就是我懒。
Audio的API很丰富,很给力,播放器各个部件可以和它很好的衔接。
最后要说说设计,这次的设计我很喜欢,基本符合了一开始的想法。因为CSS3提供了很好透明度,投影的支持,这让我们实现简单透明质感效果变得很简单,这个设计只有一张图片,就是背景图,是我去Los Angeles飞机上拍的。
代码分享
一开始在纠结,播放器应该写成一个构造函数呢,还是原型对象,抑或是普通对象。这个问题我以后要研究一下,基于构造函数,原型对象,对象的编程,各有什么利弊。反正我这次我直接构造一个Player对象,毕竟我目前觉得还没有需要实例化多个播放器,或者要继承之类的。就算以后需要,只要新建一个构造函数,并把它的原型指向我现在编写的这个Player对象就好了。
var Player = {
playList: [{ title: "天空之城", singer: "久石让", URL: ["http://upload20.music.qzone.soso.com/30479511.mp3","http://landodesign.net/sky.mp3"]},
{title: "金鱼的眼泪", singer: "纪佳松", URL: ["http://wma.9ku.com/2011/3/26/1.mp3"]}],//播放列表数据
currentSong: {},//当前播放歌曲
audio: document.getElementById("audio"),//绑定页面相应的Dom,下面几个都是
list: document.getElementById("playlist"),
search: document.getElementById("btn"),
keyword: document.getElementById("search"),
state: document.getElementById("state"),
init: function () {//初始化函数
this.renderList();//渲染播放列表
var self=this;
this.search.onclick = function () { Player.add(self.keyword.value); }//绑定点击搜索歌曲的按钮
},
add: function (keyword) {//添加歌曲函数,参数是关键字
var self = this;
this.search.innerHTML = "我挖啊挖...";
var xhr = new XMLHttpRequest();//初始化XHR对象,下面是发送数据和一些准备工作
xhr.open("GET", "info2.ashx?keyword=" + window.escape(keyword), true);
xhr.onreadystatechange = function () { if (xhr.readyState == 4) callback(xhr.responseText); }
xhr.send(null);
function callback(data) {//回调函数
if (data) {//如果有数据传回来
var obj = eval(data);//解析为对象并且push进播放列表中
self.playList.push(obj);
self.renderList();//渲染列表
if(self.audio.src==""||self.audio.ended)self.play(obj);//如果是之前没有播放或者已经结束了,就直接播放搜索出来的那首歌
}
else {//如果搜不到或者出错都会返回空字符串,然后会有这个提示
alert("木有这首歌啵~");
}
self.search.innerHTML = "再来一首吧";
}
},
play: function (song) {
var self = this;
this.audio.src = song.URL[0];//把第一个URL赋给audio
this.audio.addEventListener("error", function () {//如果出错了并且有两个URL,就尝试第二个;下面是都各种事件的绑定
if (self.audio.src == song.URL[0] && song.URL[1]) self.audio.src = song.URL[1];
else self.changeState("链接失败!");
});
this.audio.addEventListener("waiting", function () {
self.changeState("等待缓冲...");
});
this.audio.addEventListener("playing", function () {
self.changeState("正在播放 :" + song.title + " - " + song.singer, "正在播放 :" + song.title);
});
this.audio.addEventListener("pause", function () {
self.changeState("暂停播放 :" + song.title + " - " + song.singer, "正在播放 :" + song.title);
});
this.audio.addEventListener("ended", function () {//如果播放完了,就随机播放下一首,不知道是不是算法有问题,感觉很不随机
self.play(self.playList[Math.ceil(self.playList.length * Math.random()) - 1]);
});
this.audio.play();//播放
this.currentSong = song;
this.renderList();
},
renderList: function () {//渲染列表函数
var self = this;
this.list.innerHTML = "";//先清空Dom
for (var i = 0; i < this.playList.length; i++) {//一个个的节点加上去
var a = document.createElement("a");
if (this.playList[i] == self.currentSong) a.setAttribute("class", "playing");
a.innerHTML = this.playList[i].title + " - " + this.playList[i].singer //+ (this.playList[i] == self.currentSong ? " [正在播放...]" : "");
a.href = "javascript:void(0)";
a.onclick = (function (song) {//这里要创建闭包
return function () {
self.play(song);
}
})(this.playList[i]);
this.list.appendChild(a);
}
},
changeState: function (info, title) {//改变状态函数
this.state.innerHTML = info;//这个是控制栏上面的哪里
document.title = title || info;//这个是网页标题,如果没有第二参数则使用前一个参数
}
}
window.onload = Player.init();
未来的改进
做完这个蛮有成就感的,还打算以后继续完善一下。下面是目前的一些想法:
- 兼容性问题。这个问题很蛋疼,IE和FF都不支持的确不太好。我目前比较倾向两种兼容方案:第一种是嵌入Flash,在非Chrome和Safari浏览器中调用Flash来播放音乐,但是这样子就把播放器回归到传统了,也不能叫HTML5播放器了,这样意义不大。另外是编码兼容方案,每一首歌抓取的时候把两种编码的地址都拿下来,根据不同浏览器播放不同的。这种方法就直接无视了不支持HTML5的浏览器,但是我觉得最大问题是:去哪里抓取ogg格式啊?
- 使用模式问题。现在用户要听音乐,唯一办法就是输入关键字,然后歌曲就自动列入播放列表。这种使用模式太麻烦了,我也想过很多模式,譬如:默认载入一些新歌在列表中,或者好像豆瓣虾米那样可以随便听听,还是完全由用户自己管理,然后还有把歌曲信息保存在客户端或者云端。
呃……目前就想到这些,欢迎大家给点意见。
参考资料
HTML5 Audio/Video 标签,属性,方法,事件汇总
浙公网安备 33010602011771号