参考文章:
https://css-tricks.com/custom...
https://blog.hellojs.org/crea...css
对于 <video>
标签,有一个名为 'controls' 的属性,按以下写法就能给播放器增长原生的暂停/开始、进度条、音量、视频最大化这些基础功能。html
<video id="myVideo" controls ></video>
可是原生控件每每没法知足咱们的一些需求,因此自定义用户控件仍是很必要的。
首先声明一个变量,咱们把 <video id="video"></video>
作以下定义html5
let videoElement = document.getElementById('video'); let $videoElement = $('#video');
如何实现自定义控件,提及来也很简单,只须要借助几个 H5 播放器的事件和属性就能够了:web
暂停和开始是最基本的功能了,实现起来很简单
开始:chrome
videoElement.play()
暂停:bootstrap
videoElement.pause()
因此只须要在当前视频暂停的时候调用play()
方法就能够继续播放,同理在视频正在播放的时候调用pause()
就能够了。
提的一提的是『判断当前视频是否暂停』
若是仅用videoElement.paused
来判断视频暂停可能会有报错api
The play() request was interrupted by a call to pause().
,通过查询,最后使用了isPlaying 变量来判断视频是否暂停浏览器
let isPlaying = videoElement.currentTime > 0 && !videoElement.paused && !videoElement.ended && videoElement.readyState > 2;
最后暂停/开始事件的方法以下:dom
let playpauseToggle = function(e){ let isPlaying = videoElement.currentTime > 0 && !videoElement.paused && !videoElement.ended && videoElement.readyState > 2; if(!isPlaying) { videoElement.play(); } else { videoElement.pause(); } return false; }
这个就很容易了,借助两个参数便可;duration
能够获取视频总时长currentTime
能够获取视频当前时长ide
视频总时长在视频载入后获取一次便可,
视频当前时间则不一样,每当视频进度更新一次后,视频当前时间就须要随之更新loadedmetadata
事件:获取视频元数据。timeupdate
事件:视频播放后,更新播放进度的事件。 会有明确的进度变化,能够获取到currentTime
值得一提的是,用duration
和 currentTime
获取到的数据格式是保留了若干位小数,以秒为单位的一个值,一般须要根据须要格式化一下,我为了将『十分钟二十四秒』格式化为10:24
这样的格式,建立了以下方法
let numberToTime = function(number){ number = parseInt(number,10); let minues = 0; let second = 0; minues = parseInt(number / 60, 10); second = number % 60 if(minues<10){ minues = '0'+ minues } if(second<10){ second = '0'+ second } return minues + ':' + second; }
以及监听对应事件并更新当前时间的代码以下
$videoElement.on('loadedmetadata', function() { $('.duration').text(numberToTime(videoElement.duration)); }); $videoElement.on('timeupdate', function() { $('.current').text(numberToTime(videoElement.currentTime)); });
<div class="progressTime"> <span class="current">00:00</span> / <span class="duration">00:00</span> </div>
没有进度条的视频不是好视频,实现一个进度条很重要
声明一点:进度条这里的样式我使用了 bootstrap 的 dom 结构以下
<div class="progress"> <div class="progress-bar progress-bar-primary" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" style="width: 0%;"> </div> <div class="bufferBar progress-bar progress-bar-buffered"></div> </div>
有两个条,一个是当前进度,一个是缓冲进度。
基本原理也很简单,获取 当前时间/总时长 * 100% 的值,而后把这个值赋给进度条对应 dom 的样式中的 'width',经过timeupdate
事件不断更新便可。
$videoElement.on('timeupdate', function() { let currentPos = videoElement.currentTime; let maxduration = videoElement.duration; let percentage = 100 * currentPos / maxduration; $('.progress-bar-primary').css('width', percentage + '%'); })
缓冲进度条和上面的实现基本一致,对应上面currentPos
值的是
let currentBuffer = videoElement.buffered.end(0)
进度条不但要能看进度,还要能拖拽进度
拖拽进度的思路是:根据鼠标在进度条上的mousedown
事件和mouseup
事件鼠标的 X 坐标量(含正负)变化来肯定当前进度的变化程度。
具体代码以下:
let timeDrag = false; /* Drag status */ $('.progress').mousedown(function(e) { timeDrag = true; updatebar(e.pageX); }); $(document).mouseup(function(e) { if(timeDrag) { timeDrag = false; updatebar(e.pageX); } }); $(document).mousemove(function(e) { if(timeDrag) { updatebar(e.pageX); } }); let updatebar = function(x) { let progress = $('.progress'); let maxduration = videoElement.duration; //视频总时长 let position = x - progress.offset().left; //变化量 let percentage = 100 * position / progress.width(); //超出范围的修正 if(percentage > 100) { percentage = 100; } if(percentage < 0) { percentage = 0; } //更新进度条和当前时间 $('progress-bar').css('width', percentage+'%'); videoElement.currentTime = maxduration * percentage / 100; };
音量的控制很容易,主要借助如下方法和属性,具体的交互能够为所欲为的实现。以前还有看过一篇文章是介绍丧心病狂的音量键的,能够学习学习[滑稽]:http://adquan.com/post-10-410...
videoElement.muted = true //静音 videoElement.muted = false //解除静音 videoElement.volume = 1 //设置音量为最大值 videoElement.volume = 0.5 //设置音量为50% videoElement.volume = 0 //设置音量为最小值
全屏是一个兼容起来有点麻烦的功能。
若是你要为 firefox 写用户控件的话,调用全屏 api 的就得是 <video>
和<div class="controls"><div>
的共同父元素,否则会发现全屏后,你的用户控件看不到了。(但然,firefox 原生的用户控件比 chrome 的好看一百倍,因此你要是用原生的用户控件,那直接 element.requestFullscreen()
就行)
同时咱们也记下这个 tips :能调用全屏 api 的不仅是<video>
<div class="live__player"> <video></video> <div class="controls"></div> </div>
//全屏 function fullScreenOn(element) { if(element.requestFullscreen) { element.requestFullscreen(); } else if(element.mozRequestFullScreen) { $('.live__player')[0].mozRequestFullScreen(); } else if(element.msRequestFullscreen){ element.msRequestFullscreen(); } else if(element.oRequestFullscreen){ element.oRequestFullscreen(); } else if(element.webkitRequestFullscreen) { element.webkitRequestFullScreen(); } else{ var docHtml = document.documentElement; var docBody = document.body; var videobox = document.getElementById('sfLive'); var cssText = 'width:100%;height:100%;overflow:hidden;'; docHtml.style.cssText = cssText; docBody.style.cssText = cssText; videobox.style.cssText = cssText+';'+'margin:0px;padding:0px;'; document.IsFullScreen = true; } $controls.css('z-index','2147483647'); }
此处传入的值就是videoElement
<small>`(videoElement = document.getElementById('video');)`</small>
另一点,最后一行代码作的是:把咱们自定义控件的 z-index 属性设置为浏览器最大值。缘由是,webkit 内核的浏览器在全屏的时候,视频的 z-index 变为了浏览器容许的最大值,咱们把自定义控件的 z-index 也设置为最大值,就能避免用户控件被视频遮住。
一样的,退出全屏模式的代码以下:
function fullScreenOff() { if (document.exitFullscreen) { document.exitFullscreen(); } else if (document.msExitFullscreen) { document.msExitFullscreen(); } else if (document.mozCancelFullScreen) { document.mozCancelFullScreen(); } else if(document.oRequestFullscreen){ document.oCancelFullScreen(); } else if (document.webkitExitFullscreen){ document.webkitExitFullscreen(); } else { var docHtml = document.documentElement; var docBody = document.body; var videobox = document.getElementById('sfLive'); docHtml.style.cssText = ""; docBody.style.cssText = ""; videobox.style.cssText = ""; document.IsFullScreen = false; } $('.live__playcontrol').css('z-index','1'); }
检查视频是否全屏的代码以下:
let isFullScreen = document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement
视频开始/暂停的判断依据
文中已写,代码以下
let isPlaying = videoElement.currentTime > 0 && !videoElement.paused && !videoElement.ended && videoElement.readyState > 2;
firefox 全屏后,自定义的用户控件不见了
文中已写,和其余浏览器不一样,firefox 不是用 `<video>`元素的 dom 对象去调用`requestFullscreen()`,而是用 `<video>`元素的父元素去调。
shadowDom 隐藏的问题
若是你发现,你明明把 <video>
元素的属性controls
去掉了,可是原生控件依然显示,那么只有用 CSS 去干掉它
video::-webkit-media-controls-enclosure { display:none !important; }