參考文章:
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; }