封装一个 html5 audio 接口的 音乐播放器。html5 的音频接口,传统借助插件才能播放的时代逐渐走向历史的档案。调用其API 简单实现一个可以播放控制的播放器。目前仅实现了播放控制,进度条定位。至于开慢进,音量大小,专辑播放,歌词显示等暂时不弄。 audio 相关的 api
控制函数功能说明
load() 加载音频、视频软件,通常不必调用,除非是动态生成的元素,用来在播放前预加载play() 加载并播放音频、视频文件,除非文件已经暂停在其他位置,否则默认重头开始播放pause() 暂停处于播放状态的音频、视频文件 audio 的只读媒体特性有: 只读属性属性说明
duration 获取媒体文件的播放时长,以s为单位,如果无法获取,则为NaNpaused 如果媒体文件被暂停,则返回true,否则返回falseended 如果媒体文件播放完毕,则返回truestartTime 返回起始播放时间,一般是0.0,除非是缓冲过的媒体文件,并一部分内容已经不在缓冲区error 在发生了错误后返回的错误代码currentSrc 以字符串形式返回正在播放或已加载的文件,对应于浏览器在source元素中选择的文件
audio 可脚本控制的特性值:
autoplay 自动播放已经加载的的媒体文件,或查询是否已设置为autoplayloop 将媒体文件设置为循环播放,或查询是否已设置为loopcurrentTime 以s为单位返回从开始播放到目前所花的时间,也可设置currentTime的值来跳转到特定位置controls 显示或者隐藏用户控制界面volume 在0.0到1.0间设置音量值,或查询当前音量值muted 设置是否静音autobuffer 媒体文件播放前是否进行缓冲加载,如果设置了autoplay,则忽略此特性
对于这些属性,主流的浏览器都支持。可是别以为就没有了兼容性,在音频播放流中,有两个阵营。firefox 和 opera 支持 ogg 音频,safari 和 ie 支持 mp3.幸好Google的chrome都支持。 前台页面结构
01
02
03
04
05
06
07 0:00
08 -0:00
09
1 0
11
12
13
14
JavaScript:
001 $('document').ready(function() {
002 //---------------------------------------------初始化
003 var mediaSource = [{
004 title: '浮光掠影',
005 srcMedia: 'ablum/浮光掠影.mp3'
006 }, {
007 title: 'Just A Kiss',
008 srcMedia: 'ablum/Just A Kiss.mp3'
009 }, {
010 title: '关忆北',
011 srcMedia: 'ablum/关忆北.mp3'
012 }, {
013 title: '知足',
014 srcMedia: 'ablum/知足.mp3'
015 }, {
016 title: 'wish',
017 srcMedia: 'ablum/wish.mp3'
018 }, {
019 title: '当我离开你的时候',
020 srcMedia: 'ablum/当我离开你的时候.mp3'
021 }]; 022 023
024 var init = function() { 025
026 var initData = {
027 media : '#media',
028 xStart : '#pregrassbg',
029 bgWidth : '#pregrassbg',
030 oplay : '#play',
031 precolor : '#pregrasscolor',
032 playTime : '#playTime',
033 surplusTime : '#surplusTime',
034 plist : '#plist',
035 title : '#title',
036 autoPlay : true,
037 meSou : mediaSource
038 }
039 //创建音频对象
040 mymedia = new PlayAudio(initData); 041
042 //绑定播放暂停控制
043 $('#play').bind('click', function() {
044 mymedia.playAudio();
045 });
046 //绑定定位歌曲控制
047 $('#pregrassbg').bind('click', function(e) {
048 mymedia.localProgress(e);
049 });
050 //绑定列表播放
051 $('#plist li').live('click', function(e) {
052 mymedia.chooseMedia($(this));
053 });
054 //绑定音频播放结束
055 $('#media').bind('ended', function() {
056 mymedia._ended();
057 })
058 $('#prev').bind('click', function() {
059 mymedia.prevMedia();
060 })
061 $('#next').bind('click', function() {
062 mymedia.nextMedia(); 063
0 })
065 //载入window 时初似乎定时器
066 $(window).bind('load', function() {
067 mymedia.openInter();
068 mymedia.loadWindow();
069 })
070 }()
071 //----------------------------------------------音频播放构造函数 072
073 function PlayAudio(initObj) {
074
075 this.media = $(initObj.media)[0];
076 this.xStart = $(initObj.xStart).offset();;
077 this.bgWidth = $(initObj.bgWidth).width();;
078 this.oplay = $(initObj.oplay);;
079 this.precolor = $(initObj.precolor);
080 this.playTime = $(initObj.playTime);
081 this.surplusTime = $(initObj.surplusTime);
082 this.plist = $(initObj.plist);
083 this.title = $(initObj.title);
084 this.autoPlay = initObj.autoPlay;
085 this.meSou = initObj.meSou;
086 this.mediaLength = this.meSou.length;
087
088 that = this;
0 this.timer = null;
090 this.mediaIndex = 0;
091 //window改变是处理播放条位置
092 $(window).bind(\"resize\", function() {
093 that.xStart = $('#pregrassbg').offset();
094 });
095 }
096 //===============================================播放暂停控制
097 PlayAudio.prototype.playAudio = function() {
098 if(this.media.paused) {
099 this._play(this.oplay);
100 } else {
101 this._pause(this.oplay)
102 }
103 }
104 //===============================================定位歌曲的方法
105 PlayAudio.prototype.localProgress = function(e) {
106 this._play(this.oplay);
107 var scale = (e.pageX - this.xStart.left) / this.bgWidth;
108 var duraTimes = this.media.duration;
109 this.media.currentTime = duraTimes * scale;
110 this.precolor.width(this.bgWidth * scale);
111 }
112 //===============================================开启定时器,更像进度条
113 PlayAudio.prototype.openInter = function() {
114 if(this.timer != null) {
115 clearInterval(this.timer);
116 }
117 var _this = this; //定时器会改变 this
118 this.timer = setInterval(function() {
119 _this._update();
120 }, 1000);
121 }
122 //==============================================更新入口
123 PlayAudio.prototype._update = function() {
124 this._updateProgress();
125 this._updatTime();
126 }
127 //===============================================进度条更新方法
128 PlayAudio.prototype._updateProgress = function() {
129 var duraTime = media.duration;
130 var curTime = media.currentTime;
131 var scale = curTime / duraTime;
132 this.precolor.width(this.bgWidth * scale);
133 }
134 //===============================================时间更新方法
135 PlayAudio.prototype._updatTime = function() {
136 var duraTime = media.duration;
137 var curTime = media.currentTime;
138 if(duraTime == NaN) {
139 duraTime = 0;
140 }
141 var leftTime = parseInt(curTime);
142 var rughtTime = parseInt(duraTime - curTime);
143 this.playTime.html(this._converToTime(leftTime));
144 this.surplusTime.html(this._converToTime(rughtTime));
145 }
146 //===============================================播放函数
147 PlayAudio.prototype._play = function(obj) {
148 this.media.play();
149 this.title.siblings().text('正在播放:');
150 this.openInter();
151 obj.attr('class', 'pause');
152 }
153 //===============================================暂停函数
154 PlayAudio.prototype._pause = function(obj) {
155 this.media.pause();
156 clearInterval(this.timer);
157 obj.attr('class', 'on');
158 }
159 //===============================================播放完毕
160 PlayAudio.prototype._ended = function() {
161 if(this.autoPlay) {
162 this.mediaIndex++;
163 if(this.mediaIndex == this.mediaLength) {
1 alert('已经是最后一首了');
165 this._endedStyle();
166 return;
167 }
168 this._playlist(this.mediaIndex);
169 } else {
170 this._endedStyle();
171 }
172 }
173 //==============================================
174 PlayAudio.prototype._endedStyle = function() {
175 this.precolor.width(0);
17 this.surplusTime.html(this._converToTime(parseInt(media.dura6 tion)));
177 this._pause(this.oplay);
178 this.playTime.html('0:00');
179 }
180 //===============================================选择列表列表
181 PlayAudio.prototype.chooseMedia = function(obj) {
182 var item = obj.attr('data-index');
183 this.mediaIndex = item;
184 this._playlist(item);
185 }
186 //===============================================上一曲
187 PlayAudio.prototype.nextMedia = function() {
188 this.mediaIndex++;
1 if(this.mediaIndex == this.mediaLength) {
190 alert('已经是最后一首了');
191 this._pause(this.oplay);
192 this.mediaIndex = this.mediaLength - 1;
193 return;
194 }
195 this._playlist(this.mediaIndex);
196 }
197 //===============================================下一曲
198 PlayAudio.prototype.prevMedia = function() {
199 if(this.mediaIndex == 0) {
200 alert('已经是第一首了');
201 this._pause(this.oplay);
202 this.mediaIndex = 0;
203 this.flag = true;
204 return;
205 }
206 this.mediaIndex--;
207 this._playlist(this.mediaIndex);
208 }
209 //================================================窗口初始化,生成列表
210 PlayAudio.prototype.loadWindow = function() {
211 this.media.src = this.meSou[0].srcMedia;
212 var html = '';
213 for(var item in this.meSou) {
214 html += '
215 }
216 this.plist.append(html);
217 this.title.text(this.meSou[0].title);
218 this.plist.children().eq(0).css({
219 'background': '#eee',
220 'color': '#f80'
221 });
222 }
223 //================================================更新 url 地址函数
224 PlayAudio.prototype._playlist = function(currIndex) {
225 this.media.src = this.meSou[currIndex].srcMedia;
226 this._play(this.oplay);
227 this.plist.children().eq(currIndex).css({
228 'background': '#eee',
229 'color': '#f80'
230 }).siblings().css({
231 'background': '#fff',
232 'color': '#000'
233 });
234 this.title.text(this.meSou[currIndex].title);
235 }
236 //================================================工具函数,将秒转换为分钟
237 PlayAudio.prototype._converToTime = function(time) {
238 //将剩余秒数转化为分钟
239 var min = Math.floor((time / 60) % 60);
240 //将剩余秒数转化为秒钟
241 var sec = Math.floor(time % 60);
242 var cTime;
243 if(sec < 10) {
244 sec = '0' + sec;
245 }
246 cTime = min + ':' + sec
247 return cTime;
248 } 249 })
———————————————————————————————
之前是写了一个纯过程,然后再封装成一个oop的方式。。。比较让我郁闷的是事件绑定的时候,有的时候是直接绑定事件处理函数,如果事件需要传参数,则需要绑定一个匿名函数,再在匿名函数内运行带参数的事件处理程序。如果需要传入事件对象,还需要在匿名函数中传入e。对应的事件处理函数则可以返回一个 闭包。如下:
01 $('#pregrassbg').bind('click',localProgress('#play'));
02 function localProgress(obj){
03 return function(e){
04 _play(obj);
05 var scale = (e.pageX-xStart.left) / bgWidth;
06 var duraTimes = media.duration;
07 media.currentTime = duraTimes * scale;
08 $('#pregrasscolor').width(bgWidth * scale);
09 } 10 } 或者
01 //绑定定位歌曲控制
02 $('#pregrassbg').bind('click',function(e){
03 mymedia.localProgress(e);
04 });
05 //===============================================定位歌曲的方法
06 PalyAudio.prototype.localProgress = function(e){
07 this._play(this.oplay);
08 var scale = (e.pageX-this.xStart.left) / this.bgWidth;
09 var duraTimes = this.media.duration;
10 this.media.currentTime = duraTimes * scale;
11 this.precolor.width(this.bgWidth * scale); 12 }
两种方式都比较灵活。
此外,还有 设置定时器的时候,this指针的嫁接改变。如下代码
01 //===============================================开启定时器,更像进度条
02 PalyAudio.prototype._openInter = function(){
03 if(this.timer != null){
04 clearInterval(this.timer);
05 }
06 var _this = this; //定时器会改变 this,
07 this.timer = setInterval(function(){
08 _this._playProgress();
09 },1000); 10 }
11 //===============================================进度条更新方法
12 PalyAudio.prototype._playProgress = function(){
13 var duraTime = this.media.duration;
14 var curTime = this.media.currentTime;
15 var scale = curTime / duraTime;
16 this.precolor.width(this.bgWidth * scale);
17 18 }
如果 不先保存 this。直接在定时器中使用 this ,最终的 _playProgress 方法调用的时候无法取到 this.bgWidth,即构造函数的字段。
播放器界面没有做美化。 异常与错误还没做,下一步完善。
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- 7swz.com 版权所有 赣ICP备2024042798号-8
违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务