手机版

vue实现自定义H5视频播放器的方法步骤

时间:2021-08-22 来源:互联网 编辑:宝哥软件园 浏览:

前言

前段时间基于某视频剪辑软件写了一个自定义的录像播放器组件,踩了一些小坑,这里做一下复盘分享出来,避免日后重复踩坑.

设计阶段

这里就直接放几张完成后的播放状态图吧,界面布局基本就是弯曲大众适配一把梭,也比较容易。

需要实现的几个功能基本都标注出来了;除了还有一个视频加载失败的.下面就这届上代码了;刚开始构思的时候考虑了一下功能的实现方式: 一是用原生的数字正射影像图操作,获取录像元素后,用听器来监听;二是用某视频剪辑软件的方式绑定事件监听;最后图方便采用了两者结合的方式,但是总感觉有点乱,打算后期再做一下代码格式优化。

录像组件实现过程

组件模板部分

主要是播放器的几种播放状态的逻辑理清楚就好了,即: 播放中,缓存中,暂停,加载失败这几种情况,下面按功能分别说一下

模板' div class='视频播放器!-播放器界面;兼容ios控件-video ref=' video ' v-if=' showVideo ' web kit-playsinline=' true ' playsinline=' true ' x-web kit-airplay=' true ' X5-video-player-type=' H5 ' X5-video-player-全屏=' true ' X5-video-orientation=' portraint ' style=' object-fit : fill ' preload=' auto ' muted=' true '海报=' https://照片。MAC 69。com/1800您的浏览器不支持html 5/视频!-兼容机器人端层级问题,弹出层被覆盖- img v-show='!显示视频| |状态。isend ' class=' poster ' src=' http :3359 photo。MAC 69。com/180205/18020526/a9ypqozt0g。jpg ' alt!-控制窗口- div class='control' v-show='!国家。iserror ' ref=' control ' @ touch start=' touch enter video ' @ touch end=' touch leave video '!-播放|| 暂停|| 加载中-div class=' play ' @触摸开始。stop=' click playn ' v-show='状态。controlbtnshow ' img v-show='!状态。播放!state.isLoading' src='http:/./资产/视频/内容_ BTN _播放。SVG ' img v-show='状态。玩!state.isLoading' src='http:/./资产/视频/内容_ BTN _暂停。SVG ' div class=' loader ' v-show='状态。正在加载' div class='加载程序-内球-剪辑-旋转分部/分部/分部/分部!-控制条-div class=' control-bar ' : style=' { visibility : state。control bar show“visible”:“hidden”}“span class=”time“{ video。显示时间} }/span span class=' progress ' ref=' progress ' img class=' progress-BTN忽略' : style=' { translate 3360 ' translate 3d($ { video。进步。当前} px,0,0)` } ' src=' http 3360././资产/视频/内容_ IC _ tutu。SVG ' span class=' progress-loaded ' : style=' { width : ` $ { video。已加载} % `} '/span!-设置手动移动的进度条-span class=' progress-move ' @ touch move。停下来。protect=' moveIng($ event)' @ touch start。stop=' move start($ event)' @ touch end。stop=' move end($ event)'/span/span span class=' total-time ' { video。总时间} }/span span class='全屏' @ click='全屏' img src=' http :/./资产/视频/内容_ IC _增量。' SVG ' alt/span/div/div!-错误弹窗-div class=' error ' v-show=' state。iserror ' p class=' lost '视频加载失败/p p class='重试@单击='重试'点击重试/p/div/模板播放器初始化

这里有个坑点我就是当父元素隐藏即display:none时,getBoundingClientRect()是获取不到元素的尺寸数值的,后来查了移动用户号码簿号码文档,按上面说的改了一下边界也没有用,最后尝试设置元素能见度属性为隐藏的后发现就可以获取了getBoundingClientRect() :返回元素的大小及其相对于视口的位置,这个美国石油学会(美国石油协会)在计算元素相对位置的时候挺好用的。

init() { //初始化视频,获取录像元素这个$video=这个$ El。getelementsbytagname(' video ')[0];这个。init player();}, //初始化播放器容器,获取视频播放器元素//getBoundingClientRect()以客户可视区的左上角为基点进行位置计算initPlayer() { const $player=this .$ elconst $progress=this .$el.getElementsByClassName('进度')[0];//播放器位置this . player . $ player=$ player this。进度栏。$ progress=$ progress这个。玩家。pos=$ player。getboundingclientrect();这个。进度栏。pos=$进度。getboundingclientrect()。这个。视频。进步。宽度=数学。round($进度。getboundingclientrect().宽度);},播放暂停点击

我这里把事件监听都放在只有满足正在播放视频才开始事件监听;感觉原生监听和某视频剪辑软件方式的监听混合在一起写有点别扭.伊格尔.这里需要对这个$video.play()做一个异常处理,防止录像刚开始加载的时候失败,如果视频链接出错,玩方法调用不了会抛错,后面我也用了录像的错误事件去监听播放时的错误

//点击播放暂停按钮单击playn(){ if(this。国家。正在加载)返回;this . IsFirstTouch=false this . state . playing=!这个。国家。玩耍;这个。国家。isend=false如果(这个$video) { //播放状态if(this . state . playing){ 0尝试{这个.$视频。play();this . isposetouch=false//监听缓存进度这个$视频。addeventlistener(' progress ',e={ this。getloadtime();});//监听播放进度这个$视频。addeventlistener(' time update ',throttle(this.getPlayTime,100,1));//监听结束这个$video.addEventListener('ended ',e={ //重置状态这个。国家。播放=假;这个。国家。isend=true这个。国家。controlbtnshow=true这个。视频。显示时间=' 00:00 ';这个。视频。进步。电流=0;这个$视频。当前时间=0;});} catch (e) { //捕获全球资源定位器(统一资源定位符)异常出现的错误} } //停止状态else { this.isPauseTouch=true这个$视频。pause();} } },视频控制条显示和隐藏

这里需要加两个开关;首次触屏和暂停触屏;做一下显示处理即可

//触碰播放区touchevendeo(){ if(this。IsFirstTouch)返回;如果(这个。hidetime){ cleartime out(这个。hide time);this.hideTimer=null} this。国家。controlbtnshow=true这个。国家。controlbarshow=true}, //离开播放区touchLeaveVideo(){ if(this。IsFirstTouch)返回;如果(这个。hidetime){ cleartime out(这个。hide time);} //暂停触摸,不隐藏如果(这个。isposetouch){这个。国家。controlbtnshow=true这个。国家。controlbarshow=true} else { this。hidetime=setTimeout(()={ this。国家。controlbarshow=false//加载中只显示正在加载如果(这个。国家。正在加载){这个。国家。control btnshow=true} else { this。国家。controlbtnshow=false} this.hideTimer=null},3000);} },视频错误处理和等待处理

这里错误直接用错误事件,加载中用拖延事件来监听视频阻塞状态,等待数据加载用的等待事件;显示对应的装货动画即可

//加载动画@关键帧旋转{ 0% { transform : rotate(0);} 50% { transform:旋转(180度);} 100% { transform : rotate(360);}}.装载机{ width: 58px高度: 58px背景: rgba(15,16,17,0.3);边界半径: 50%;相对位置:球夹旋转{绝对位置:左侧: 50%;前:名50%;transform: translate(-50%,-50%);div { width: 15px高度: 15px边界半径: 100%;margin: 2px动画-填充-模式:两者;border: 2px实心# fff边框-底部-颜色:透明;高度: 26px宽度: 26px背景:透明;显示器:内联块;动画:旋转0.75秒0秒线性无限;} }}播放时间设置

基本就是录像对象的当前时间和期间这两个属性;这里注意下视频如果没有设置预加载属性事先装好的话,在录像元素初始化的时候是获取不到期间的.那你只能在播放的时候去拿了。

//获取播放时间getPlayTime(){ const percent=this .$video.currentTime/this .$ video.durationthis。视频。进步。电流=数学。圆(这个。视频。进步。宽度*百分比);//赋值时长这个。视频。总时间=TiME Arles(今年.$视频。持续时间);这个。视频。显示时间=TiMer(这.$视频。currettime);}, //获取缓存时间getLoadTime() { //console.log('缓存了.',这个$视频。缓冲的。end(0));这个.视频.加载的=(这个.$video.buffered.end(0)/this .$视频。持续时间)* 100;},手动滑动进度条控制

这里直接用触控事件即可;注意触摸端中使用e.changedTouches因为当手指离开屏幕,触摸和目标触摸中对应的元素会同时移除,而参数信息仍然会存在元素。

触摸:当前屏幕上所有触摸点的列表;目标触点:当前对象上所有触摸点的列表;changedTouches:涉及当前(引发)事件的触摸点的列表//手动调节播放进度moveStart(e) {},moveIng(e) { //console.log('触摸中.');让CurrentX=e . TargetTouch[0].页面x让offsetX=CurrentX-这个。进度栏。pos。向左;//边界检测if(offset x=0){ offset x=0 } if(offset x=this。视频。进步。width){ offsetX=this。视频。进步。宽度}这个。视频。进步。current=offsetX让百分比=这个。视频。进步。当前/这个。视频。进步。宽度;这个$视频。持续时间。设置播放时间(百分比,这个.$video.duration) },moveEnd(e) { //console.log('触摸结束.');让currentX=e.changedTouches[0].页面x让offsetX=CurrentX-这个。进度栏。pos。向左;这个。视频。进步。current=offsetX//这里的偏移量都是正数让百分比=偏移量x/这个。视频。进步。宽度;这个$视频。持续时间。设置播放时间(百分比,这个.$video.duration) },//设置手动播放时间setPlayTime(百分比,totalTime) { this .$video.currentTime=Math.floor(百分比*总时间);},全屏功能

这个功能在手机上会有写兼容性问题.有待完善

//设置全屏全屏(){ console.log('点击全屏.');if(!这个。国家。全屏){这个。国家。全屏=真;这个$视频。webkitrequest全屏();} else { this。国家。全屏=假;文件。webkitcancelfilscreen();}坑点汇总

1.视频预加载才能获取时长需要设置预加载预载="自动"2。Element.getBoundingClientRect()方法返回元素的大小及其相对于视口的位置父元素设置display:none时获取不到尺寸数据民谣改为visibility:hidden3.play()方法异常捕获尝试{

版权声明:vue实现自定义H5视频播放器的方法步骤是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。