回忆
算了不回忆了
直接搞起,翻开JS1中写的bvd.js
播放视频
- 播放按钮隐蔽
视频最先播放
当点击播放按钮的时刻,播放按钮将会隐蔽,播放视频,这个不难,在JS1中我们就已完成。但我们转变一下头脑,给视频增添点击tap事宜,使视频播放,再触发播放事宜,从而让播放按钮隐蔽pro.initEvent = function(){ var that = this; //给播放按钮图片增添事宜 this.vimg.addEventListener('tap',function(){ that.video.play(); }) //视频点击停息或播放事宜 this.video.addEventListener('tap',function(){ if(this.paused || this.ended) { //停息时点击就播放 if(this.ended) {//假如播放终了,就重头最先播放 this.currentTime = 0; } this.play(); } else { //播放时点击就停息 this.pause(); } }) //视频播放事宜 this.video.addEventListener('play',function(){ that.vimg.style.display = 'none'; }) //猎取到元数据 this.video.addEventListener('loadedmetadata',function(){ that.vC.querySelector('.duration').innerHTML = stom(this.duration); }); }
下方掌握条逐渐隐蔽
隐蔽并非难点,主要的是逐渐的隐蔽,在这里我们有这么几种解决方案:- 定时器
- css3 动画帧
在这里我们2种结合起来运用
起首我们先定义好一组动画
@keyframes vhide {0% {opacity: 1;}100% {opacity: 0;}}
@-webkit-keyframes vhide {0% {opacity: 1;}100% {opacity: 0;}}
.vhidden {
animation: vhide 3.5s ease-in;
-webkit-animation: vhide 3.5s ease-in;
}
其作用就是通明度3.5秒内1=>0,ease-in 就是 由慢到快 的过分结果。有不懂css动画能够问问度娘哦
然后我们给视频最先播放事宜的时刻给掌握条增添vhidden款式类
//视频播放事宜
this.video.addEventListener('play',function(){
that.vC.classList.add('vhidden');
})
测试结果,果真3.5s内,掌握条 逐步通明,题目是3.5s后,通明度又回到了1,这里我解说一下,是由于动画帧默许是回弹的,我们能够加个款式
.vhidden {
animation: vhide 3.5s ease-in;
-webkit-animation: vhide 3.5s ease-in;
animation-fill-mode:forwards;
-webkit-animation-fill-mode: forwards;
}
CSS3 属性 animation-fill-mode 用来定义元素在动画完毕后的模样。
animation-fill-mode 的默许值是 none,也就是在动画完毕以后不做任何修正,假如把animation-fill-mode 改成 forwards 则动画完毕后元素的款式会变成动画末了一个关键帧所划定的款式。
加上这个款式后,果真3.5s后,动画不再回弹了,然则这里要注意一下,掌握条并非不在了而是通清晰明了,假如这时候我们有写掌握条的点击时候,那末在掌握条位置点击,照样会触发事宜,所以呢,我们还能够写上一段setTimeout来,让掌握条3.5s后隐蔽,这个人人能够自行弃取
//视频播放事宜
this.video.addEventListener('play',function(){
that.vimg.style.display = 'none';
that.vC.classList.add('vhidden');
that.vCt = setTimeout(function(){
that.vC.style.visibility = 'hidden';
},3400);
})
为何动画历程是3.5s,但是js是是3.4s后实行,这里只是在未写animation-fill-mode:forwards的情况下做个保险
正在播放中
嘿嘿,视频能够播放啦!那末如今我们该考虑一下播放中有哪些事要做呢?
1. 掌握条进度条逐步增进
我们须要给视频增添一条timeupdate音视频播放位置发作转变时的事宜
我们先在猎取视频元数据事宜中,把视频的长度给拿下来
//猎取到元数据
this.video.addEventListener('loadedmetadata',function(){
that.vDuration = this.duration;
that.vC.querySelector('.duration').innerHTML = stom(that.vDuration);
});
再从视频播放进度更新事宜中盘算比例,设置进度条的宽度
//视频播放中事宜
this.video.addEventListener('timeupdate', function() {
var currentPos = this.currentTime;//猎取当前播放的位置
//更新进度条
var percentage = 100 * currentPos / that.vDuration;
//设置宽度
that.vC.querySelector('.timeBar').style.width = percentage + '%';
});
能够看到我们的进度条君愈来愈膨胀了。
2. 当前播放时候变化
同时,我们的当前播放时候显现也在timeupdate事宜中设置
//视频播放中事宜
this.video.addEventListener('timeupdate', function() {
var currentPos = this.currentTime;//猎取当前播放的位置
//更新进度条
var percentage = 100 * currentPos / that.vDuration;
that.vC.querySelector('.timeBar').style.width = percentage + '%';
//更新当前播放时候
that.vC.querySelector('.current').innerHTML = stom(currentPos);
});
停息 or 住手
当我们点击视频时,假如是停息,那就最先播放,并触发播放事宜,反之视频在播放中,点击视频就会停息,并触发停息事宜。
0. 时候定格
啦啦啦,停息播放,timeupdate事宜天然就不触发啦,所以进度条和当前播放时候就不会变啦。
1. 播放按钮显现
在停息的时刻,显现出按钮就行啦
//停息or住手
this.video.addEventListener('pause',function(){
that.vimg.style.display = 'block';
});
2. 下方掌握条显现
掌握条显现,直接去除谁人vhidden款式类就好啦
//停息or住手
this.video.addEventListener('pause',function(){
that.vimg.style.display = 'block';
that.vC.classList.remove('vhidden');
that.vC.style.visibility = 'visible';
});
如许写看模样是没错啦,然则,假如人人在之前隐蔽掌握条的时刻写了setTimeout的话,这个时刻就要清撤除哦。
//停息or住手
this.video.addEventListener('pause',function(){
that.vimg.style.display = 'block';
that.vC.classList.remove('vhidden');
that.vC.style.visibility = 'visible';
that.vCt && clearTimeout(that.vCt);
});
快进快退
一个叼叼哒的小视频播放器怎么能够少的了可进可退能屈能伸呢?
来,我们先为video增添左滑右滑事宜
//视频手势右滑动事宜
this.video.addEventListener('swiperight',function(e){
this.currentTime += 5;
});
//视频手势左滑动事宜
this.video.addEventListener('swipeleft',function(e){
this.currentTime -= 5;
});
能够在电脑上调试会直接进度变0,一最先我也疑惑呢,厥后发明手机上webview中好像是可行的。
关于 进度条拖动转变视频进度 我暂时不盘算写,由于我还没写。
全屏播放
能够人人会比较关注这个吧:
ios端:去除video标签webkit-playsinline属性即可,由于ios对h5的video标签支撑照样比较不错的
//挪用原生体式格局 全屏播放
pro.nativeMax = function(){
if(!window.plus){
//非html5+环境
return;
}
if($.os.ios){
console.log('ios')
this.video.removeAttribute('webkit-playsinline');
}else if($.os.android){
console.log('android');
var url = this.video.querySelector('source').src;
var Intent = plus.android.importClass("android.content.Intent");
var Uri = plus.android.importClass("android.net.Uri");
var main = plus.android.runtimeMainActivity();
var intent = new Intent(Intent.ACTION_VIEW);
var uri = Uri.parse(url);
intent.setDataAndType(uri, "video/*");
main.startActivity(intent);
}
}
在initEvent中增添点击 全屏 事宜
this.vC.querySelector('.fill').addEventListener('tap',function(){
that.nativeMax();
});
如许做有点鸡肋啊,就不能来点通用的?
确切这个题目我想了一晚上,决议再拿点干货来。
先给个状况,默许为mini播放
var bvd = function(dom) {
var that = this;
$.ready(function() {
//猎取视频元素
that.video = document.querySelector(dom || 'video');
//猎取视频父元素
that.vRoom = that.video.parentNode;
//元素初始化
that.initEm();
//事宜初始化
that.initEvent();
//纪录信息
that.initInfo();
//当前播放形式 false 为 mini播放
that.isMax = false;
})
}
//纪录信息
pro.initInfo = function() {
var that = this;
//在onload状况下,offsetHeight才会猎取到准确的值
window.onload = function(){
that.miniInfo = {//mini状况时的款式
width: that.video.offsetWidth + 'px',
height: that.video.offsetHeight + 'px',
position: that.vRoom.style.position,
transform: 'translate(0,0) rotate(0deg)'
}
var info = [
document.documentElement.clientWidth || document.body.clientWidth,
document.documentElement.clientHeight || document.body.clientHeigth
],
w = info[0],
h = info[1],
cha = Math.abs(h - w) / 2;
that.maxInfo = {//max状况时的款式
width: h + 'px',
height: w + 'px',
position: 'fixed',
transform: 'translate(-' + cha + 'px,' + cha + 'px) rotate(90deg)'
}
}
}
//全屏 mini 两种形式切换
pro.switch = function() {
var vR = this.vRoom;
//猎取须要转换的款式信息
var info = this.isMax ? this.miniInfo : this.maxInfo;
for(var i in info) {
vR.style[i] = info[i];
}
this.isMax = !this.isMax;
}
//全屏按钮
this.vC.querySelector('.fill').addEventListener('tap', function() {
//that.nativeMax();
that.switch();
});
瞧一瞧拉,看一看拉
看起来觉得很不错呢,应用css3的位移和扭转,让视频全屏在了屏幕前,然则题目也随之而来了
- 播放按钮 以及 掌握条 在全屏下 好像隐蔽了,实际上是video标签盖在了父元素之上,我们作出响应的调解
css
.bad-video {
position: relative;
/*overflow: hidden;*/
background-color: #CCCCCC;
}
js
max设置当中,设置zIndex值
that.maxInfo = {//max状况时的款式
zIndex:99,
width: h + 'px',
height: w + 'px',
position: 'fixed',
transform: 'translate(-' + cha + 'px,' + cha + 'px) rotate(90deg)'
}
- 横向全屏后,摆布滑动事宜没有随着方向转变
//视频手势右滑动事宜
this.video.addEventListener('swiperight', function(e) {
console.log('right');
this.currentTime += 5;
});
//视频手势左滑动事宜
this.video.addEventListener('swipeleft', function(e) {
console.log('left');
this.currentTime -= 5;
});
这TM就很为难了,岂非我全屏后,手机横放,还去高低快进快退?
这时候刻怎么办呢,不要方
手势滑动事宜
我们先给video注册一个事宜列表
var events = {};
//增添 或许删除事宜
pro.eve = function(ename, callback, isF) {
if(callback && typeof(callback) == 'function') {
isF && arguments.callee(ename);
events[ename] = callback;
this.video.addEventListener(ename, events[ename]);
console.log('增添事宜:' + ename);
return;
}
var fun = events[ename] || function(){};
this.video.removeEventListener(ename, fun);
console.log('删除事宜:' + ename);
return fun;
}
给video事宜增添一个代办来删除增添事宜,isF就是在新增这个事宜是不是删除之前的这个雷同的事宜,由于增添事宜用匿名函数的话,是不能删除的,如许设置一个代办就能够把动态增添的事宜纪录在events内里,便于操纵
这时候我们补上修正当前播放进度和音量的功用
//跳转视频进度 单元 秒
pro.setCurrentTime = function(t){
this.video.currentTime += t;
}
//设置音量大小 单元 百分比 如 0.1
pro.setVolume = function(v){
this.video.volume+= v;
}
再经由过程代办给video增添摆布高低滑动的事宜
//视频手势右滑动事宜
this.eve('swiperight',function(){
that.setCurrentTime(5);
});
//视频手势左滑动事宜
this.eve('swipeleft', function(e) {
that.setCurrentTime(-5);
});
//视频手势上滑动事宜
this.eve('swipeup',function(){
that.setVolume(0.2);
});
//视频手势下滑动事宜
this.eve('swipedown', function(e) {
that.setCurrentTime(-0.2);
});
ok,四个方向的滑动事宜已增添过去了,但这是mini形式播放时的事宜,在全屏播放下,四个方向事宜并没有随着video元素方向的转变而转变,这下须要再经由过程最最最笨的体式格局推断是不是全屏从而触发的事宜
//视频手势右滑动事宜
this.eve('swiperight',function(){
if(that.isMax){
return that.setVolume(0.2);
}
that.setCurrentTime(5);
});
//视频手势左滑动事宜
this.eve('swipeleft', function() {
if(that.isMax){
return that.setVolume(-0.2);
}
that.setCurrentTime(-5);
});
//视频手势上滑动事宜
this.eve('swipeup',function(){
if(that.isMax){
return that.setCurrentTime(-5);
}
that.setVolume(0.2);
});
//视频手势下滑动事宜
this.eve('swipedown', function() {
if(that.isMax){
return that.setCurrentTime(5);
}
that.setVolume(-0.2);
});
怎样,虽然看起来有点stupid,然则很有用呢
5+客户端全屏解决方案
虽然说在5+客户端,android能够挪用原生的体式格局播放,但照样差强人意,我们能够再来看一套解决方案
初始化时,纪录mini时的款式,全屏时,经由过程修正视频宽度为屏幕高度,视频高度修正为视频宽度,再应用5+的屏幕扭转,设置全屏,隐蔽状况栏
0)去除手势事宜推断
由于如今是预备转变挪动装备的方向,所以,手势方向会随着装备方向转变
1)去除 css3 扭转以及位移
//纪录信息
pro.initInfo = function() {
var that = this;
//在onload状况下,offsetHeight才会猎取到准确的值
window.onload = function() {
that.miniInfo = { //mini状况时的款式
zIndex: 1,
width: that.video.offsetWidth + 'px',
height: that.video.offsetHeight + 'px',
position: that.vRoom.style.position
}
that.maxInfo = { //max状况时的款式
zIndex: 99,
width: '100%',
height: that.sw + 'px',
position: 'fixed'
}
}
}
2)该用5+的设置全屏以及隐蔽状况栏
//全屏 mini 两种形式切换
pro.switch = function() {
var vR = this.vRoom;
//猎取须要转换的款式信息
var info = this.isMax ? this.miniInfo : this.maxInfo;
for(var i in info) {
vR.style[i] = info[i];
}
this.isMax = !this.isMax;
plus.navigator.setFullscreen(this.isMax);
if(this.isMax) {
//横屏
plus.screen.lockOrientation("landscape-primary");
} else {
//竖屏
plus.screen.lockOrientation("portrait-primary");
}
}
3)全屏状况下,android端返回键,触发退出全屏
pro.initEvent = function() {
//.......省略其他代码
this.oback = $.back;
//监听安卓返回键
$.back = function() {
if(that.isMax) {
that.switch();
return;
}
that.oback();
}
}
结果图
5+重力感到切换全屏
嘿嘿,一个在挪动端的播放器怎么能少得了 自动切换 反正屏呢?
在个小节当中就讲了怎样手动切换全屏,接下来重力感到切换横屏,须要用到5+的API Accelerometer 加速度感到
简单说:重力加速度感到能够设想成一个小球在坐标系中
三个方向上的加速度。永久以手机屏幕为准
啥是加速度?额,就是物理书上的
手机程度安排向上是y轴正向
向右是x轴正向,向外是z轴正向
啥是xyz轴?额,就是高数书上的
哎呀,你把手机竖屏正派的放在地上,你人正派走上去,如今你站在你的手机的屏幕上,然后你的右手翻开蜷缩,这就是x轴,你如今看着前面,这就是y轴,你的头顶就是z轴。如许讲邃晓了不,然则并非真的要你踩手机,23333
您也能够挑选检察其他解说:Android-传感器开辟-方向推断
- x,y轴变化:
手机屏幕向上程度安排时: (x,y,z) = (0, 0, -9.81)
当手机顶部抬起时: y减小,且为负值
当手机底部抬起时: y增添,且为正值
当手机右边抬起时: x减小,且为负值
当手机左边抬起时: x增添,且为正值 - z轴的变化:
手机屏幕向上程度安排时,z= -9.81
手机屏幕竖直安排时, z= 0
手机屏幕向下程度安排时,z= 9.81 - 屏幕反正切换前提
y<=-5时, 切换为竖向
x<=-5时, 换为横向
ok,我们新增2个要领,用于翻开和封闭装备监控
//开启方向感到
pro.startWatchAcc = function(){
var that = this;
this.watchAccFun = plus.accelerometer.watchAcceleration(function(a) {
if(that.getIsMax()){
//当前为全屏状况
//推断是不是满足竖屏Mini状况
a.yAxis>=5 && that.setIsMax(false);
}else{
//当前为Mini状况
//推断是不是满足全屏Max状况
Math.abs(a.xAxis) >=5 && that.setIsMax(true);
}
}, function(e) {
//出错了大不了 不自动扭转呗 让它手动 切换
console.log("Acceleration error: " + e.message);
that.clearWatchAcc();
},{
frequency:1200
});
}
//封闭方向感到
pro.clearWatchAcc = function(){
this.watchAccFun && plus.accelerometer.clearWatch(this.watchAccFun);
}
然后在初始化的时刻默许翻开方向监控
var bvd = function(dom) {
var that = this;
$.ready(function() {
//...
})
$.plusReady(function() {
that.startWatchAcc();
})
}
再把横向全屏改成,可双向横屏
真机调试看看
嘿嘿,我们再给全屏播放时增添一个锁定按钮,让装备不监控 重力感到,也不响应视频的点击播放停息事宜
先做一个锁定按钮
固然,锁定图片,地点也改成用base64,最好也用js动态天生标签
设置它的基础款式,靠右,高低垂直居中,默许隐蔽
.lock {
padding: .3rem;
width: 3rem;
height: 3rem;
position: absolute;
right: .5rem;
top: 50%;
transform: translateY(-50%);
-webkit-transform: translateY(-50%);
visibility: hidden;
}
好,我们来整顿一下逻辑,
1)默许在mini播放时,lock隐蔽
2)全屏播放时,lock显现,然则也会随着掌握条 在4s内向右隐蔽
3)全屏停息时,lock也随着掌握条 一向显现
4)点击lock锁定时,提醒已锁定,掌握条马上隐蔽,lock4s内向右隐蔽,视频点击事宜替换为显现lock图标,android返回键事宜改成不做任何,封闭重力监控
5)点击lock解锁时,提醒已解锁,android返回键改成 切换为mini状况,开启重力监控
我擦,实在做起来照样挺忧郁的,主如果逻辑处置惩罚比较痛楚
0)增添一个向右挪动的动画,3s耽误后 1s内 实行完动画
@keyframes lockhide {0% {transform: translate(0%,-50%);}100% {transform: translate(120%,-50%);}}
webkit-keyframes lockhide {0% {transform: translate(0%,-50%);}100% {transform: translate(120%,-50%);}}
.lockhidden {
animation: lockhide 1s 3s linear;
-webkit-animation: lockhide 1s 3s linear;
animation-fill-mode:forwards;
-webkit-animation-fill-mode: forwards;
}
1)全屏时显现lock
pro.switch = function() {
//...
//全屏时 显现锁定 图标
this.vlock.style.visibility = this.isMax ? 'visible' : 'hidden';
}
2)全屏播放时,lock显现,然则也会随着掌握条 在4s内向右隐蔽
我们在播放时增添lock的隐蔽动画,
3)全屏停息时,lock也随着掌握条 一向显现
4)点击lock锁定时,提醒已锁定,掌握条马上隐蔽,lock4s内向右隐蔽,视频点击事宜替换为显现lock图标,android返回键事宜改成不做任何,封闭重力监控
5)点击lock解锁时,提醒已解锁,android返回键改成 切换为mini状况,开启重力监控
//锁定屏幕
pro.lockScreen = function() {
$.toast('锁定屏幕');
var that = this;
//替换video点击事宜为 显现 lock图标,并保留 video之前的事宜
this.videoTapFn = this.eve('tap', function() {
that.lockT = setTimeout(function(){
that.vlock.classList.add('lockhidden');
},500);
//重新最先播放款式
that.vlock.classList.remove('lockhidden');
that.vlock.style.visibility = 'visible';
}, true);
//隐蔽掌握条
this.vC.style.visibility = 'hidden';
//给Lock图标增添 隐蔽款式类
this.vlock.classList.add('lockhidden');
//锁定屏幕时,不监控重力感到
this.clearWatchAcc();
//标识当前变动的Lock状况
this.isLock = true;
}
//解锁屏幕
pro.unlockScreen = function() {
$.toast('解锁屏幕');
//替换回video之前的点击事宜
this.eve('tap', this.videoTapFn, true);
//给Lock图标清晰 隐蔽款式类
this.vlock.classList.remove('lockhidden');
//不锁定屏幕时,监控重力感到
this.startWatchAcc();
//标识当前变动的Lock状况
this.isLock = false;
}
666)末了给我们亲爱的lock图标增添一枚抚摩事宜,以及android返回键的事宜变动
//全屏 时 锁定点击事宜
this.vlock.addEventListener('tap', function() {
if(that.isLock) {
that.unlockScreen();
return;
}
that.lockScreen();
});
this.oback = $.back;
//监听安卓返回键
$.back = function(){
if(that.isMax){
if(!that.isLock){
//全屏状况下 按下返回键 时,1s内不监控重力,防备返回Mini状况时和重力感到并发事宜
setTimeout(function(){
that.startWatchAcc();
},1000);
that.clearWatchAcc();
that.switch();
}
return;
}
that.oback();
}
}
好了!本文5+全屏demo 源码地点
写博客不容易,然则那种分享的心境是很不错的,何尝不是另一种复习和提高呢?
感谢列位。
本文相干文章:H5打造属于本身的视频播放器 专栏