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

这里就直接放几张完成后的播放状态图吧,界面布局基本就是flex+vw适配一把梭,也比较容易.

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

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

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

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

video组件实现过程

组件模板部分

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

<template> <div> <!-- 播放器界面; 兼容ios controls--> <video ref="video" v-if="showVideo" webkit-playsinline="true" playsinline="true" x-webkit-airplay="true" x5-video-player-type="h5" x5-video-player-fullscreen="true" x5-video-orientation="portraint" preload="auto" muted="true" poster="https://photo.mac69.com/180205/18020526/a9yPQozt0g.jpg" :src="src" @waiting="handleWaiting" @canplaythrough="state.isLoading = false" @playing="state.isLoading = false, state.controlBtnShow = false, state.playing=true" @stalled="state.isLoading = true" @error="handleError" >您的浏览器不支持HTML5</video> <!-- 兼容Android端层级问题, 弹出层被覆盖 --> <img v-show="!showVideo || state.isEnd" src="https://photo.mac69.com/180205/18020526/a9yPQozt0g.jpg" alt > <!-- 控制窗口 --> <div v-show="!state.isError" ref="control" @touchstart="touchEnterVideo" @touchend="touchLeaveVideo" > <!-- 播放 || 暂停 || 加载中--> <div @touchstart.stop="clickPlayBtn" v-show="state.controlBtnShow"> <img v-show="!state.playing && !state.isLoading" src="" > <img v-show="state.playing && !state.isLoading" src="" > <div v-show="state.isLoading"> <div> <div></div> </div> </div> </div> <!-- 控制条 --> <div :style="{ visibility: state.controlBarShow ? 'visible' : 'hidden'}"> <span>{{video.displayTime}}</span> <span ref="progress"> <img :style="{transform: `translate3d(${video.progress.current}px, 0, 0)`}" src="" > <span :style="{ width: `${video.loaded}%`}"></span> <!-- 设置手动移动的进度条 --> <span @touchmove.stop.prevent="moveIng($event)" @touchstart.stop="moveStart($event)" @touchend.stop="moveEnd($event)" ></span> </span> <span>{{video.totalTime}}</span> <span @click="fullScreen"> <img src="" alt> </span> </div> </div> <!-- 错误弹窗 --> <div v-show="state.isError"> <p>视频加载失败</p> <p @click="retry">点击重试</p> </div> </div> </template>

播放器初始化

这里有个坑点我就是当父元素隐藏即display:none时,getBoundingClientRect()是获取不到元素的尺寸数值的,后来查了MDN文档,按上面说的改了一下border也没有用,最后尝试设置元素visibility属性为hidden后发现就可以获取了.
getBoundingClientRect() : 返回元素的大小及其相对于视口的位置, 这个api在计算元素相对位置的时候挺好用的.

init() { // 初始化video,获取video元素 this.$video = this.$el.getElementsByTagName("video")[0]; this.initPlayer(); }, // 初始化播放器容器, 获取video-player元素 // getBoundingClientRect()以client可视区的左上角为基点进行位置计算 initPlayer() { const $player = this.$el; const $progress = this.$el.getElementsByClassName("progress")[0]; // 播放器位置 this.player.$player = $player; this.progressBar.$progress = $progress; this.player.pos = $player.getBoundingClientRect(); this.progressBar.pos = $progress.getBoundingClientRect() this.video.progress.width = Math.round($progress.getBoundingClientRect().width); },

播放 && 暂停点击

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

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/a8ae179e6daadd516909eace1b33a862.html