摘要:回顾算了不回顾了直接搞起,打开中写的播放视频播放按钮隐藏视频开始播放当点击播放按钮的时候,播放按钮将会隐藏,播放视频,这个不难,在中我们就已经实现。
回顾
算了不回顾了
直接搞起,打开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+的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打造属于自己的视频播放器 专栏
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/87857.html
摘要:回顾打造属于自己的视频播放器篇在上一章节之中,已经把篇给大致样式显现了出来,接下来应该是篇了,可是在写之前有必要先整理一下思绪,盲目乱写是不对的,喝杯茶,撩撩妹,生活多美妙,写起代码来自然心情好思路正。 回顾 H5打造属于自己的视频播放器(HTML篇)在上一章节之中,已经把HTML篇给大致样式显现了出来,接下来应该是JS篇了,可是在写之前有必要先整理一下思绪,盲目乱写是不对的,喝杯茶,...
摘要:回顾打造属于自己的视频播放器篇在上一章节之中,已经把篇给大致样式显现了出来,接下来应该是篇了,可是在写之前有必要先整理一下思绪,盲目乱写是不对的,喝杯茶,撩撩妹,生活多美妙,写起代码来自然心情好思路正。 回顾 H5打造属于自己的视频播放器(HTML篇)在上一章节之中,已经把HTML篇给大致样式显现了出来,接下来应该是JS篇了,可是在写之前有必要先整理一下思绪,盲目乱写是不对的,喝杯茶,...
前言 众所周知,16年无疑是直播行业的春天,同时也是H5的一次高潮。so,到现在用H5技术在移动端做网页直播也是见怪不怪了,但是!!!今天我们的主角是webApp下播放视频参考文献:1)HTML5+CSS3+JQuery打造自定义视频播放器2)mui Html5 Video 实现方案3)移动端HTML5视频播放优化实践 搬好凳子看HTML 首先我们在HB下创建一个新的app项目,名称为 欠债 sh...
前言 众所周知,16年无疑是直播行业的春天,同时也是H5的一次高潮。so,到现在用H5技术在移动端做网页直播也是见怪不怪了,但是!!!今天我们的主角是webApp下播放视频参考文献:1)HTML5+CSS3+JQuery打造自定义视频播放器2)mui Html5 Video 实现方案3)移动端HTML5视频播放优化实践 搬好凳子看HTML 首先我们在HB下创建一个新的app项目,名称为 欠债 sh...
前言 众所周知,16年无疑是直播行业的春天,同时也是H5的一次高潮。so,到现在用H5技术在移动端做网页直播也是见怪不怪了,但是!!!今天我们的主角是webApp下播放视频参考文献:1)HTML5+CSS3+JQuery打造自定义视频播放器2)mui Html5 Video 实现方案3)移动端HTML5视频播放优化实践 搬好凳子看HTML 首先我们在HB下创建一个新的app项目,名称为 欠债 sh...
阅读 2582·2021-11-23 09:51
阅读 2403·2021-09-30 09:48
阅读 2026·2021-09-22 15:24
阅读 995·2021-09-06 15:02
阅读 3275·2021-08-17 10:14
阅读 1911·2021-07-30 18:50
阅读 1959·2019-08-30 15:53
阅读 3149·2019-08-29 18:43