四、精简提炼

我们的播放器基本实现了,但是代码复用不高,所以我们要进行封装,以插件的形式体现。

1.插件的基本运行代码如下:

;(function(undefined){‘use strict‘;

... ...

})()

上述代码就是基本的插件代码,下面详细记录这段代码所表示的意思。

前面的分号,可以解决插件与其它js合并时,别的代码可能会产生的错误问题;

“(function(){})()”这个结构表示立即执行第一个括号内的函数,其实立即执行函数还有另一种写法,“(function(){}())”。看大家的喜好,我一般喜欢用第一种;

“undefined”做为参数传入,因为在老一辈的浏览器是不被支持的,直接使用会报错,js框架要考虑到兼容性,因此增加一个形参undefined,就算有人把外面的 undefined 定义了,插件里面的 undefined 依然不受影响。

严格模式开发

下面进一步补充代码函数内代码:

‘use strict‘;

这行代码表示严格模式,顾名思义,严格模式就是使得 Javascript 在更严格的条件下运行,有助于我们更规范的开发。如果在语法检测时发现语法问题,则整个代码块失效,并导致一个语法异常。如果在运行期出现了违反严格模式的代码,则抛出执行异常。

定义我们的播放器插件“playMythology”

下面我们真正开始我们的插件代码了,目前整个代码如下:

;(function(undefined){‘use strict‘;var_global;functionplayMythology(opt) {

... ...

}

playMythology.prototype={};//将插件对象暴露给全局对象_global= (function() {return this || (0, eval)(‘this‘);

}());if (typeof module !== "undefined" &&module.exports) {

module.exports=playMythology;

}else if (typeof define === "function" &&define.amd) {

define(function() {returnplayMythology;

});

}else{!(‘playMythology‘ in _global) && (_global.playMythology =playMythology);

}

})()

定义“_global”,并把全局环境赋值给一个_global。

并把当前顶级对象赋值给这个变量,代码如下:

_global = (function() {return this || (0, eval)(‘this‘);

}());

看这段代码又是个立即执行函数,不是上面提到的第一种的立即执行函数,而是这种第二种立即执行函数:(functiong(){})结构;首先先介绍一下eval()函数的作用:eval() 函数计算JavaScript字符串,并把它作为脚本代码来执行,如果参数是一个表达式,eval() 函数将执行表达式,如果参数是Javascript语句,eval()将执行Javascript语句。然后在逐一分析语句:return this表示返回当前对象;第一个括号内的逗号操作符 对它的每个操作数求值(从左到右),并返回最后一个操作数的值,那么这个(0, eval)(‘this‘)相当于eval(‘this’),那么为什么不用eval(‘this’),而用(0, eval)(‘this‘)呢?在严格模式下,如果没有给 this指定值的话,它就是未定义的,为了防止在严格模式下window变量被赋予undefined,使用(0, eval)(‘this’)就可以把this重新指向全局环境对象。因为(0, eval)(‘this’)通过逗号表达式对它的操作数执行了GetValue,计算出一个值,让this的值指向了全局对象;而eval(‘this’)计算出的是一个引用,是一个直接调用,方法中的this值是obj的引用。

定义“playMythology”,表示我们插件的名称。然后我们给这个函数添加属性,通过prototype来添加,简单解释一下prototype是函数的一个属性,并且是函数的原型对象。prototype只能够被函数调用。

为了实现插件的模块化并且让我们的插件也是一个模块,就得让我们的插件也实现模块化的机制。这只需要判断是否存在加载器,如果存在加载器,我们就使用加载器,如果不存在加载器。我们就使用顶级域对象。下面代码就实现了这个功能:

if (typeof module !== "undefined" &&module.exports) {

module.exports=playMythology;

}else if (typeof define === "function" &&define.amd) {

define(function() {returnplayMythology;

});

}else{!(‘playMythology‘ in _global) && (_global.playMythology =playMythology);

}

介绍一下主要的运算符:“==”表示相等;“===”表示绝对相等;“!=”表示不相等;“!==”,表示严格不相等。JavaScript中,unll与undefined并不相同,但是null==undefined为真,null===undefined为假,所以null !== undefined为真。

“typeof ”表示返回数据类型,有2种使用方式:typeof(表达式)和typeof变量名,第一种是对表达式做运算,第二种是对变量做运算。返回类型为字符串,值包括如下几种:

1. ‘undefined‘              --未定义的变量或值

2. ‘boolean‘                 --布尔类型的变量或值

3. ‘string‘                     --字符串类型的变量或值

4. ‘number‘                  --数字类型的变量或值

5. ‘object‘                    --对象类型的变量或值,或者null(这个是js历史遗留问题,将null作为object类型处理)

6. ‘function‘                 --函数类型的变量或值module.exports 对象是由模块系统创建的。在我们自己写模块的时候,需要在模块最后写好模块接口,声明这个模块对外暴露什么内容,module.exports 提供了暴露接口的方法。这种方法可以返回全局共享的变量或者方法。

介绍一下AMD,AMD是一种规范就是其中比较著名一个,全称是Asynchronous Module Definition,即异步模块加载机制。从它的规范描述页面看,AMD很短也很简单,但它却完整描述了模块的定义,依赖关系,引用关系以及加载机制。感兴趣的朋友可以认真研究一下,requireJS,NodeJs,Dojo,JQuery全部在使用,可见它的价值。

2.基本函数

引入CSS文件函数:前端开发引入CSS文件是必不可少的,css主要功能是对页面布局进行美化,我希望开发的插件的皮肤可以动态设置,所以要动态引入CSS文件,定义了引入CSS文件函数,具体代码如下:

//path表示引入CSS文件路径

functioncssinto(path) {//如果CSS文件错误,抛出错误异常

if (!path || path.length === 0) {throw new Error(‘argument "path" is required !‘);

}//获取head 对象

var head = document.getElementsByTagName(‘head‘)[0];//创建link标签并插入到head标签内

var link = document.createElement(‘link‘);

link.href=path;

link.rel= ‘stylesheet‘;

link.type= ‘text/css‘;

head.appendChild(link);

}

时间转换函数:主要功能,讲audio currentTime 时间戳转换转化成“分:秒”显示格式。

//path表示引入CSS文件路径

//时间显示转换

functionconversion(value) {

let minute= Math.floor(value / 60)

minute= minute.toString().length === 1 ? (‘0‘ +minute) : minute

let second= Math.round(value % 60)

second= second.toString().length === 1 ? (‘0‘ +second) : secondreturn minute+":"+second

}

引入json文件函数:file值json文件路径,callback只得是回调函数,当文件加载完毕就调用该函数。

functionreadTextFile(file, callback) {var rawFile = newXMLHttpRequest();

rawFile.overrideMimeType("application/json");

rawFile.open("GET", file, true);

rawFile.onreadystatechange= function() {if (rawFile.readyState === 4 && rawFile.status == "200") {

callback(rawFile.responseText);

}

}

rawFile.send(null);

}

getElementsByClass:因为我们未讲window传入插件,所以有些方法我们是不能使用的,所以我们定义下面方法实现,通过class查找html中dom对象。

//判断插件是否存在“getElementsByClass”,没存在,将使用下面方法实现该功能。

if (!(‘getElementsByClass‘ inHTMLElement)) {//prototype在前面已经提到过了,通过“prototype”给HTMLElement添加属性方法“getElementsByClass”

HTMLElement.prototype.getElementsByClass= function(n) {var el =[],

_el= this.getElementsByTagName(‘*‘);for (var i = 0; i < _el.length; i++) {if (!!_el[i].className && (typeof _el[i].className == ‘string‘) && _el[i].className.indexOf(n) > -1) {

el[el.length]=_el[i];

}

}returnel;

};

((typeof HTMLDocument !== ‘undefined‘) ? HTMLDocument : Document).prototype.getElementsByClass =HTMLElement.prototype

.getElementsByClass;

}

参数合并函数: 对象合并,这个主要用于插件默认参数赋值操作,如果设置就使用新的参数,如果不设置就使用默认参数

//表示原有参数,n表示新参数,override表示是否进行覆盖

functionextend(o, n, override) {for (var key inn) {if (n.hasOwnProperty(key) && (!o.hasOwnProperty(key) ||override)) {

o[key]=n[key];

}

}returno;

}

3.基本功能

参数初始化,里面有详细的注释。

_initial: function(opt) {//默认参数

var def ={

skinID:"default", //默认皮肤路径

domID:"musicbox" //设置播放器容器ID

};//如果函数初始化时,设置参数时,进行合并,如果没有设置使用默认参数

this.def = extend(def, opt, true);//用于JSON文件存储数据

this.data ={};//播放器初始音量为0.3

this.sound = 0.3;this.currentID = 0;//创建audion

this.audion = document.createElement("AUDIO");//获取播放器dom对象

this.dom =document.getElementById(def.domID);//播放器初始音量

this.audion.volume = this.sound;//定义定时器,用于进度条调整,歌曲滚动等功能

this.timecolick;//歌曲容器

this.songBox;//播放器状态,0表示顺序播放;1表示循环播放;2表示随机播放。

this.isPlayState = 0;//歌曲列表用于存储歌曲数据

this.songList;//歌曲播放进度条

this.songProgress;//播放进度条上的播放头

this.songPlayHead;//判断歌曲是否允许滚动,0表示允许,1表示不允许

this.isSlide = 0;//播放进度,0表示初始位置

this.playprogress = 0;//最大

this.playMax = 0;//播放器是否在播放,0表示正在播放,1表示暂停

this.isPlaying = 0;//歌曲列表滚动距离

this.scollHeight = 20;//初始化播放器,并开始播放

this._GetData();

},

播放器界面初始化,并播放歌曲

//设置播放器界面

var _this = this;//把当前对象存到_this

//初始化CSS文件

cssinto("skin/" + this.def.skinID + "/css/music.css");//读取json数据

readTextFile("skin/" + this.def.skinID + "/data.json", function(text) {//数据读取到data

_this.data=JSON.parse(text);//把界面HTML代码插入容器,界面初始化

_this.dom.innerHTML= _this.data[0].MusicHtml;//设置歌曲列表

var htmlinsert = "";//过去歌曲容器dom对象

_this.songBox= _this.dom.getElementsByClass(_this.data[0].musiclistbox)[0];//存储歌曲数据

_this.songList= _this.data[0].Songlist;for (var i = 0; i < _this.songList.length; i++) {

htmlinsert+= ‘

‘ + _this.songList[i].songname + ‘‘;

}

_this.songBox.innerHTML=htmlinsert;//设置音乐列表单击事件

for (var i = 0; i < _this.songBox.childNodes.length; i++) {

(function(j) {

_this.songBox.childNodes[j].οnclick= function() {

_this._PlaySong(j);

}

})(i)

}//所有数据加载完毕,开始播放歌曲

_this._PlaySong(0);

暂停播放功能。

//播放停止按钮事件 _this.dom.getElementsByClass(_this.data[0].playBT)[0].onclick = function(e) {

//如果正在播放则停止播放

if (_this.isPlaying == 0) {this.className = "playbutton";

_this.isPlaying= 1;

_this.audion.pause()

}else //如果停止播放则开始播放

{this.className = "pausebutton";

_this.isPlaying= 0;

_this.audion.play();

}

}

歌曲切换功能,上一首,下一首切换。

//上一首按钮

_this.dom.getElementsByClass(_this.data[0].preBton)[0].onclick = function(e) {if (_this.currentID > 0) {

_this.currentID--;

}else{

_this.currentID= _this.songList.length - 1;

}

_this._PlaySong(_this.currentID)

}//下一首按钮

_this.dom.getElementsByClass(_this.data[0].nextBton)[0].onclick = function(e) {if (_this.currentID < _this.songList.length - 1) {

_this.currentID++;

}else{

_this.currentID= 0;

}

_this._PlaySong(_this.currentID)

}

随机播放功能,按钮点击后歌曲将实现随机播放。

//随机播放按钮

var randombtn = _this.dom.getElementsByClass(_this.data[0].randombtn)[0];

randombtn.οnclick= function(e) {if (_this.isPlayState == 1) {

_this.isPlayState= 0;this.className = _this.data[0].shuffle;return;

}if (_this.isPlayState == 2) {

onereplay.className= _this.data[0].replay;

}

_this.isPlayState= 1;this.className = _this.data[0].shuffleon;

}

单曲循环功能,按钮点击后歌曲将实现单曲循环播放。

//单曲循环按钮

var onereplay = _this.dom.getElementsByClass(_this.data[0].onereplay)[0];

onereplay.οnclick= function(e) {if (_this.isPlayState == 2) {

_this.isPlayState= 0;this.className = _this.data[0].replay;return;

}if (_this.isPlayState == 1) {

randombtn.className= _this.data[0].shuffleon;

}

_this.isPlayState= 2;this.className = _this.data[0].replay;

}

音量调节功能,拖放调节音量功能。

//音量调节按钮

var soundHead = _this.dom.getElementsByClass(_this.data[0].soundHead)[0];var soundBox = _this.dom.getElementsByClass(_this.data[0].soundBox)[0];var soundCurrentTime = _this.dom.getElementsByClass(_this.data[0].soundCurrentTime)[0];

soundHead.style.left= _this.sound * 100 + ‘px‘;

soundCurrentTime.style.width= _this.sound * 100 + ‘%‘;

soundHead.οnmοusedοwn= function(e) {var x = (e ||window.event).clientX;var l = this.offsetLeft;var max = soundBox.offsetWidth - this.offsetWidth;

document.οnmοusemοve= function(e) {var thisX = (e ||window.event).clientX;var to = Math.min(max, Math.max(-2, l + (thisX -x)));if (to < 0) {

to= 0;

}

soundHead.style.left= to + ‘px‘;//此句代码可以除去选中效果

window.getSelection?window.getSelection().removeAllRanges() : document.selection.empty();

_this.audion.volume= to /max;//document.querySelector(‘.now‘)

soundCurrentTime.style.width= to / max * 100 + ‘%‘;

}//注意此处是document 才能有好的拖动效果

document.οnmοuseup= function() {

document.οnmοusemοve= null;

};

}

进度条功能。

//获取进度条dom

_this.songProgress= _this.dom.getElementsByClass(_this.data[0].SongProgress)[0];//获取进度条上的播放头

_this.songPlayHead= _this.dom.getElementsByClass(_this.data[0].playHead)[0];//单击进度条 调整发播放进度

_this.songProgress.οnclick= function(e) {var x = (e ||window.event).clientX;var left = x - this.offsetLeft -_this.songPlayHead.offsetWidth;var maxwidth =_this.songProgress.offsetWidth;

_this.dom.getElementsByClass(_this.data[0].playHead)[0].style.left = left + ‘px‘;var currenttime = _this.audion.duration * (left /maxwidth)var p = left /maxwidth

_this.audion.currentTime= p *_this.audion.duration;

_this.audion.play();

};//拖动播放头,调整播放进度

_this.songPlayHead.οnmοusedοwn= function(e) {var x = (e ||window.event).clientX;var l = this.offsetLeft;var max = _this.songProgress.offsetWidth - this.offsetWidth;

_this.playMax=max;

document.οnmοusemοve= function(e) {var thisX = (e ||window.event).clientX;var to = Math.min(max, Math.max(-2, l + (thisX -x)));if (to < 0) {

to= 0;

}

_this.playprogress=to;

_this.isSlide= 1;

_this.songPlayHead.style.left= to + ‘px‘;

_this.dom.getElementsByClass(_this.data[0].SingerCurrentTime)[0].innerHTML = conversion(_this.audion.duration *(_this

.playprogress/_this.playMax));//此句代码可以除去选中效果

window.getSelection?window.getSelection().removeAllRanges() : document.selection.empty();//_this.audion.currentTime = to / max;

}//注意此处是document 才能有好的拖动效果

document.οnmοuseup= function() {

_this.isSlide= 0;

_this.audion.currentTime= (_this.playprogress / _this.playMax) *_this.audion.duration;

_this.audion.play();

document.οnmοusemοve= null;

};

定时函数功能

//定时函数

_this.timecolick= setInterval(function() {if (_this.isSlide == 1) {return;

}//设置进度条

var percent = Math.floor(_this.audion.currentTime / _this.audion.duration * 10000) / 100 + "%";

_this.songPlayHead.style.left=percent;//设置当前播放时间

_this.dom.getElementsByClass(_this.data[0].SingerCurrentTime)[0].innerHTML =conversion(_this.audion.currentTime);if(_this.audion.ended) {if (_this.isPlayState == 0) //顺序播放

{if (_this.currentID < _this.songList.length - 1) {

_this.currentID++;

}else{

_this.currentID= 0;

}

}else if (_this.isPlayState == 1) //随机播放

{

_this.currentID= Math.floor(Math.random() * _this.songList.length - 1)

}else //单曲循环

{

_this.currentID=_this.currentID;

}

console.log(_this.currentID)

_this._PlaySong(_this.currentID);

}

},100)

歌曲播放功能

__PlaySong: function(songID) {var _this = this;this.audion.setAttribute("src", this.data[0].Songlist[songID].songurl);this.dom.getElementsByClass(this.data[0].SongName)[0].innerHTML = _this.data[0].Songlist[songID].songname;

_this.dom.getElementsByClass(this.data[0].Singer)[0].innerHTML = this.data[0].Songlist[songID].songer;

_this.audion.onloadedmetadata= function() {

_this.dom.getElementsByClass(this.data[0].SingerCurrentTime)[0].innerHTML =conversion(_this.audion.currentTime);

_this.dom.getElementsByClass(this.data[0].showalltime)[0].innerHTML =conversion(_this.audion.duration)

}this.audion.play();var Songlist =_this.songBox.childNodes;for (var i = 0; i < Songlist.length; i++) {if (songID ==i) {

Songlist.item(i).setAttribute("class", this.data[0].currentSong);

}else{

Songlist.item(i).setAttribute("class", "")

}

}//console.log(_this.scollHeight*songID)

_this._scollToMusiclist(songID, _this.dom.getElementsByClass(this.data[0].MusicList)[0])

}

歌曲滚动功能。

_scollToMusiclist: function(singID, wmusicbox) {//ok 2019年4月5日,终于调试成功,长时间不开发真的不行,好多事情想不到,刚才不停的滚动现象是由于我没有对最大值进行判断,如果超过最大值,我们需要把最大值赋给变量,那样就不会不停的闪烁了。

var gundong = singID * 20;var maxgundong = wmusicbox.scrollHeight -wmusicbox.offsetHeight;if (gundong >maxgundong) {

gundong=maxgundong;

}var scollTime = setInterval(function() {

console.log(wmusicbox.scrollTop)if (wmusicbox.scrollTop

wmusicbox.scrollTop= wmusicbox.scrollTop + 1;

console.log(gundong)

}else if (wmusicbox.scrollTop >gundong) {

wmusicbox.scrollTop= wmusicbox.scrollTop - 1;

console.log("2")

}else{

console.log("=")

clearInterval(scollTime);

}

})

}

ok,这网我们的网页播放器已经全部编写完毕,我把源代码打包,提供大家下载,多提宝贵意见。 单击下载

怎么精炼java代码_网页播放器开发(四)代码精炼提纯(示例代码)相关推荐

  1. 搭建webassembly网页播放器(五)---网页播放器开发

    在前面的章节中,我们解决emcc环境以及使用emcc来编译ffmpeg得到网页开发中可以使用的js库,本章节,我们就来实现一个简单的播放器. 视频课程以及源码下载: https://edu.csdn. ...

  2. html设置播放器位置,【关于Flash网页播放器的定位与浮动的HTML代码】

    代码说明:autoStart=false或true(是否自动播放"false"是手动播放;"true"是自动播放)repeatPlay=true或false(是 ...

  3. 网页flash播放和html播放器,【关于Flash网页播放器的定位与浮动的HTML代码】

    代码说明:autoStart=false或true(是否自动播放"false"是手动播放;"true"是自动播放)repeatPlay=true或false(是 ...

  4. 手机网页播放器php,html5手机移动端视频播放代码插件

    js代码 //document.documentElement.style.overflow='hidden'; document.body.style.overflow='hidden'; zyme ...

  5. 搭建webassembly网页播放器(六)---websocket后台服务程序

    这里我们主要介绍后台搭建技术,前端搭建好后,需要后端配置展现,实现的效果就是 :网页连接上我们的 websocket服务后,我们就从H264文件中不断的提取出H264帧,然后传递给前端,前端调用web ...

  6. 搭建webassembly网页播放器(三)---emcc编译ffmpeg编译库

    经过前面的2个部分,我们完成了环境的搭建,接下来我们使用emcc编译ffmpeg库,注意同样由于软链接的缘故,我们不能在windows和linux的共享文件夹里使用emcc编译ffmpeg, 这里我们 ...

  7. 搭建webassembly网页播放器(二)---emcc环境搭建

    emcc全称 emscripten,最重要的功能就是让网页js调用c/c++ 成为可能,是我们基于webassembly搭建网页播放器必须依赖的编译工具. emcc官网的搭建教程较为简单,安装过程中最 ...

  8. java支持wmv的播放器_支持wmv、mpg、mov、avi格式的网页视频播放代码

    这2天一直在整金网奖的相关项目,比较头大的就是网页视频播放了,需要考虑各种不同格式的视频,然后找相应的视频播放器. 这次使用了2种方法对这些视频进行处理: 1.使用ckplayer网页视频播放器 ck ...

  9. 经常使用网页播放器代码

    经常使用网页播放器代码 我们在网页上看到的播放器无外乎WMP/RealOne/Macromedia Flash Player,其它的无非是面板不同,或者加入了其它控件,对于计算机上安装的一些播放器也都 ...

最新文章

  1. 使用Pycharm给Python程序传递参数
  2. [导入]用Ext做的登陆窗口的例子
  3. SQLite数据库损坏与修复
  4. C++ pair(对组)用法
  5. python基础查漏补缺1--算数、字符串与变量
  6. tornado学习笔记day04-执行顺序
  7. 防火墙的理论特性和实际功能
  8. 【心情】最近实在是太忙了,没有心情写东西!
  9. 基于DEAP库的python进化算法--遗传算法实践--配词问题
  10. 斗鱼直播云原生实践之注册中心篇
  11. mp4 box linux,MP4Box
  12. 苹果试玩换个新id行不_苹果试玩换ID可以重复任务吗
  13. 解决ueditor编辑器图片在线管理图片无法显示
  14. ps 如何裁切图片成一定的长宽高比例
  15. 机器学习神器Scikit-Learn保姆级入门教程
  16. 【今日分享】官方实例用python调用OpenAI tahcTPG的APIkey生成智能问答
  17. Hadoop大数据技术复习资料
  18. 分区空间分配:window10怎样把C盘空间分一点给D盘?
  19. sgu290:Defend the Milky Way(三维凸包)
  20. 平面和网站设计师应该去的网站

热门文章

  1. pdf怎么翻译英文?pdf怎么翻译英文文献?
  2. el-table 按照某种规则 进行自定义升序降序的排序
  3. 极限编程的幻想与真实
  4. 18.8元4G随身wifi刷openwrt改无线路由器或无线网卡
  5. 程序设计与实习MOOC 指针练习:MyMax
  6. 好奇怪呀后面加什么标点_有没有接受不了打错字或者用错标点符号的人啊?
  7. 超市商品管理系统的设计与实现
  8. 创业公司做数据分析(六)数据仓库的建设
  9. 头像上传(阿里云oss存储服务)
  10. 16.GridView宫格的实现及其显示其…