1. 程式人生 > >從零實現一個自定義html5播放器

從零實現一個自定義html5播放器

寫在最前

本次的分享是一個基於HTML5<vedio>標籤實現的一個自定義視訊播放器。其中實現了播放暫停、進度拖拽、音量控制及全屏等功能。
歡迎關注我的部落格,不定期更新中——

效果預覽


點我檢視原始碼倉庫

核心思路

我相信一定會有些沒有接觸過製作自定義播放器的童鞋對於<vedio>標籤的認識會停留在此。

<video controls="controls" autoplay="autoplay">
  <source src="movie.ogg" type="video/ogg" />
</video>

其中controls屬性經過設定,會在介面中顯示一個瀏覽器自帶的控制條。如果對於UI沒有要求的需求,其內建控制器已經可以滿足大部分的需求。當然瞭如果是這樣你們也不會看到這篇分享了=。=

隱藏控制條並模擬

那麼實現一個自定義功能的播放器關鍵就在於,我們不使用原生的控制器,將其隱藏掉之後,在下方同樣的位置通過html、css來模擬所需樣式,同時通過js來呼叫vedio標籤所暴露給我們的介面函式及屬性,以及檢測使用者的操作行為來同步的模擬UI與視訊播放資料的相應變化。

幾個核心函式及屬性的用法

myVid=document.getElementById("video1");
//控制視訊開關
myVid.play() //播放
myVid.pause() //暫停
//模擬視訊進度條
myVid.currentTime=5; //返回或設定當前視訊播放位置
myVid.duration // 返回視訊總長度
//模擬視訊音量
myVid.volume //音量
//獲取視訊當前狀態後判斷何時從loading切換為播放
myVid.readyState
//0 = HAVE_NOTHING - 沒有關於音訊/視訊是否就緒的資訊
//1 = HAVE_METADATA - 關於音訊/視訊就緒的元資料
//2 = HAVE_CURRENT_DATA - 關於當前播放位置的資料是可用的,但沒有足夠的資料來播放下一幀/毫秒
//3 = HAVE_FUTURE_DATA - 當前及至少下一幀的資料是可用的
//4 = HAVE_ENOUGH_DATA - 可用資料足以開始播放

在所有實現中的關鍵點,較為繁瑣的是對於進度條的模擬。其中使用了video標籤中的currentTime以及duration屬性,通過當前播放時間與總播放時間的比值,就可以計算出進度條相對於總長的位置。同時使用者通過拖拽進度條所最後設定的長度也可以用來反向推算出此時視訊應該播放的位置。

拖拽程式碼思路

//核心程式碼示例
var dragDis = 0
var processWidth = xxx //拖拽條總長
$('body').mousedown(function(e) {
    startX = e.clientX
    dragDis = startX - leftInit //leftInit為拖拽條起始點距螢幕左側的距離
    dragTarget.css({ //拖拽按鈕
        left: dragDis
    })
    dragProcess.css({ //進度條(藍色進度條)
        width: dragDis
    }) // 令進度條和拖拽按鈕渲染在同一位置
    videoSource.pause()
}).mousemove(function(e) {
    moveX = e.clientX
    disX = moveX - startX
    var left = dragDis + disX
    if(left > processWidth) {
        left = processWidth
    } else if(left < 0) {
        left = 0
    }
    dragTarget.css({
        left: left
    })
    dragProcess.css({
        width: left
    })
}).mouseup(function(e) {
    videoSource.play()
    videoSource.currentTime = $('藍色拖拽條').width() / processWidth * duration //拖拽後計算視訊的正確播放位置
})

同理音量的控制與其上行為基本一致,故在原始碼中作者將音量與進度部分通過不同元素進行判斷是進行進度還是音量的拖拽控制。

通過查詢視訊流狀態控制播放前的載入動畫

function ifState() {
    var state = videoSource.readyState
    if(state === 4) { //狀態為4即可播放
        videoPlayer()
    } else {
        $('.play-sym-wrapper').remove()
        $('body').append('<div class="play-sym-wrapper">![](./images/loading.gif)</div>')
        //新增loading動畫
        setTimeout(ifState, 10)
    }
}
setTimeout(ifState, 10)

核心的控制部分已經說完了,有興趣的同學可以去原始碼的html中點選播放,其中被迫有很多零碎的需求,比如點選暫停,儲存音量等等。整個視訊播放器的基礎功能實現的還算完善。

最後

慣例po作者的部落格,不定時更新中——
有問題歡迎在issues下交流,捂臉求star=。=