Day11 HTML Video Player

Demo

今天要來做一個客製化的影片播放器
主要分為四個部分:

  1. 播放與暫停影片
  2. 音量與速度
  3. 快/倒轉
  4. 控制進度條

定義變數

1
2
3
4
5
6
const myVideo = document.querySelector('video');
const playBtn = document.querySelector('.toggle')
const inputBtn = document.querySelectorAll('input')
const processbar_out = document.querySelector('.progress')
const processbar = document.querySelector('.progress__filled')
const skipbtn = document.querySelectorAll('.player__button[data-skip]')

播放與暫停影片

點選播放按鈕與畫面時,需要播放或暫停
我們觸發對象為:

1
2
myVideo.addEventListener('click',playToggle)
playBtn.addEventListener('click',playToggle)

要做的事情為:

1
2
3
4
5
6
7
8
function playToggle(e){
playBtn.innerHTML = myVideo.paused ? '❚❚' : '►'
if(myVideo.paused){
myVideo.play()
}else{
myVideo.pause()
}
}

這裡還滿容易理解的,透過myVideo.paused判斷狀態再決定播放或暫停。
playBtn用了三元運算子,判斷該顯示❚❚或►

音量與速度

一般的直覺可能會把音量和速度兩件事情拆開來做,但這邊巧妙的利用input的name來區分選取的對象,所以一開始定義的時候直接選取了所有的input

1
const inputBtn = document.querySelectorAll('input')

再透過forEach分別去做事件的觸發

1
2
3
4
5
6
7
8
function setHandler(e){
const inputName = this.name//取得名稱volume或playbackRate
const inputValue = this.value//取得該input的值
myVideo[inputName] = inputValue
}
inputBtn.forEach((input)=>{
input.addEventListener('input',setHandler)
})

注意:用 點號 . 存取時,點號右邊必須是一個可識別字(identifier),例如屬性名稱,不能是字串、變數、運算式…等。但用 中括號 [] 存取時,中括號裡面可以放字串、變數、運算式等。
來源1來源2

快/倒轉

這裡一樣透過一起選取button再forEach分別做事件
再透過dataset取得預設值,指定給currentTime

1
2
3
4
5
6
function skipHandler(){
myVideo.currentTime += parseInt(this.dataset.skip) //轉化成數字 或直接*1
}
skipbtn.forEach((btn)=>{
btn.addEventListener('click',skipHandler)
})

進度條顯示

透過時間總長度(duration)和現在時間(duration)去算出百分比

timeupdate是一個事件,當currentTime更新時會觸發timeupdate事件。詳細介紹

1
2
3
4
5
6
7
processbar.style.flexBasis = 0 //可先歸零
myVideo.addEventListener('timeupdate',function(){
let allTime = this.duration
let progress = this.duration
percent = (progress/allTime)*100
processbar.style.flexBasis = percent +'%'
})

flexBasis介紹

控制時間軸

這邊分為兩個部分,可以滑鼠按下或拖曳
拖曳必須是在mousedown的狀況下才能觸發,而且mouseup時必須關閉
觸發對象為整個時間軸

1
const processbar_out = document.querySelector('.progress')

1
2
3
4
5
6
7
8
9
10
processbar_out.addEventListener('mousedown', addListener);

function addListener (e) {
processbar_out.addEventListener('mousedown', gotoTime);
processbar_out.addEventListener('mousemove', gotoTime);
};

document.addEventListener('mouseup', function(){
processbar_out.removeEventListener('mousemove', gotoTime);
});

這裡我們透過mousedown之後,重新再定義一次觸發條件,即符合我們要的mousedown後才能mousemove。
而在這邊我認為mouseup觸發的對象不是processbar_out,使用者在拖曳時,有可能會離開我們原本的目標processbar_out,導致關閉不了mousemove,所以我將mosueup觸發對象設定為整個document

最後執行任務

1
2
3
4
5
6
7
function gotoTime(e){
let getPercent = (e.offsetX/this.offsetWidth)*100
//將百分比轉換回該影片實際時間位置
let currentTime = (getPercent*myVideo.duration)/100
processbar.style.flexBasis = getPercent +'%'
myVideo.currentTime = currentTime
}

  1. 取得滑鼠位置與processbar_out的寬算出百分比
  2. 因為我們要時間指定給currentTime所以要將百分比轉換回正確的時間值

補充

原始範例的做法是定義一個mousedown=false的變數去判斷是否滑鼠按下來做觸發,
其中有一個很酷的寫法:

1
progress.addEventListener('mousemove', (e) => mousedown && scrub(e));

這裡的&&而且的意思,在這藏了一個判斷式,也就是要執行scrub的條件必須左右都為true,當mousedown = true,右邊的scrub才會執行(也就是我們要的效果,mousedown才能mousemove)

0%