iT邦幫忙

1

JS30 Day 11 - Custom Video Player學習筆記

今天要的題目是要來客製化一個影片播放器,做完之後,更加熟悉video的一些屬性跟方法,如果不是有什麼特別需求,我覺得controls ( ),就很夠用了。

完成品如下:

https://ithelp.ithome.com.tw/upload/images/20200608/201261826ijyuuGb02.png

首先都獲取我們會用到的元素


const player = document.querySelector('.player');
// 播放器
const video = player.querySelector('.viewer');
// 進度條外層
const progress = player.querySelector('.progress');
// 進度條內層
const progressBar = player.querySelector('.progress__filled');
// 播放暫停圖標
const toggle = player.querySelector('.toggle');
// 快轉倒退圖標
const skipButtons = player.querySelectorAll('.skip');
// range input
const ranges = player.querySelectorAll('.player__slider');

再來就賦予各個元素對應事件。

timeupdate:當currentTime更新時會觸發timeupdate事件,也就是當我們有改變影片時間軸就會觸發(如影片正在播放,進度條也會跟著改變)。


//   點選影片會進行播放或暫停
video.addEventListener('click', togglePlay);
//   點圖標會進行播放或暫停
toggle.addEventListener('click', togglePlay);
//   而在播放或暫停時候又會觸發切換按鈕圖標的函數
video.addEventListener('play', updateButton);
video.addEventListener('pause', updateButton);
//   當currentTime更新時候觸發進度條
video.addEventListener('timeupdate', handleProgress);

// 對每個skip btn增添click事件,並呼叫skip函數
skipButtons.forEach(button => button.addEventListener('click', skip));

// 對每個range input增添change,mousemove(連續觸發)事件,並呼叫RangeUpdate函數
ranges.forEach(range => range.addEventListener('change', handleRangeUpdate));
ranges.forEach(range => range.addEventListener('mousemove', handleRangeUpdate));

// 對進度條增添事件,可利用鼠標移動進度到指定位置。

// 判斷是否按下鼠標,預設為false
let mousedown = false;
progress.addEventListener('click', scrub);
// 當在進度條移動時,並且按下鼠標,會計算出進度條位置
progress.addEventListener('mousemove', (e) => mousedown && scrub(e));
progress.addEventListener('mousedown', () => mousedown = true);
progress.addEventListener('mouseup', () => mousedown = false);

而在函數部分:

播放切換,利用 video[屬性]的方式,來替代判斷式。


function togglePlay() {
    // 判斷影片是否停止,如果停就播放,反之。
    const method = video.paused ? 'play' : 'pause';
    video[method](); //  video.play() or  video.pause();

    // 等同於
    // if(){
    //     video.play();
    // }else{
    //     video.pause();
    // }
}

按鈕切換

textContent:等同於innerText,都是獲取DOM元素內的文字內容,但建議用textContent,因為innerText 為非標準寫法,firefox並不支援

function updateButton() {
    // 如果影片暫停了,按鈕變成►,反之。
    const icon = this.paused ? '►' : '❚ ❚';
    console.log(icon);
    toggle.textContent = icon;
}

快轉倒退

dataset:即是以data- * 的自定義屬性


function skip() {
    // currentTime為當前影片的時間點
    // 當我按下快進25秒,利用dataset即可獲取,以data-*的自定義屬性。
    // 將字串轉成float number,並return
    video.currentTime += parseFloat(this.dataset.skip);
    console.log(this.dataset); // DOMStringMap {skip: "25"} 
}

聲音、速度控制

function handleRangeUpdate() {
    // 利用[屬性]可以節省時間去寫判斷式子
    // video.volume , video.playbackRate
    video[this.name] = this.value;
}

進度條設置,以currentTime並以%去設置對應的進度條寬度(%)。

duration:為影片總長度。
flexBasis:為預設寬度。


function handleProgress() {

    // 計算出當前時間點的百分比
    const percent = (video.currentTime / video.duration) * 100;
    // 將進度條的預設寬度設成百分比的寬度
    progressBar.style.flexBasis = `${percent}%`;
}

進度條設置(鼠標),當點擊進度條,會根據點擊的進度條位置,去改變當前時間。

e.offsetX:為當前水平位置。
progress.offsetWidth:為進度條總長度。


function scrub(e) {
    // 計算出當前進度條水平位置
    const scrubTime = (e.offsetX / progress.offsetWidth) * video.duration;
    // 更新當前影片的時間點
    video.currentTime = scrubTime;
}


尚未有邦友留言

立即登入留言