這次的內容是如何自訂視訊播放器,雖然現在HTML的**:視訊嵌入要素**的功能對想要在網站上撥放影片已經綽綽有餘了,不過能夠學習到如何自己手刻功能也是一個寶貴的經驗。
作品實做
const player = document.querySelector(".player");
const video = player.querySelector(".viewer"); //video視訊嵌入要素
const progress = player.querySelector(".progress"); //總共時間的進度條
const progressBar = player.querySelector(".progress__filled");//當下時間進度條
const toggle = player.querySelector(".toggle"); //播放鍵
const skipButtons = player.querySelectorAll("[data-skip]"); //快轉倒退鍵
const ranges = player.querySelectorAll(".player__slider"); //音量及影片速度滑動條
function togglePlay() {
const method = video.paused ? "play" : "pause";
video[method]();
}
video.addEventListener("click", togglePlay);
toggle.addEventListener("click", togglePlay);
method
,內容為一個字串,作為video方法的名稱video.paused
屬性為true(偵測影片為停止狀態則播放影片),method = "play"
。video[method]()
,JavaScript 會首先查找 method 變數所指向的字串,然後調用該字串所代表的 video 物件的方法。假設method=”play”
,則等同於video.play()
。video
及toggle
監聽到”click”
時,調用togglePlay
,即當我們點擊了畫面或者播放鍵來控制影片暫停或播放function toggleButton() {
const icon = this.paused ? "►" : "❚ ❚";
toggle.textContent = icon;
toggle.classList.add("icon-change");
setTimeout(() => {
toggle.classList.remove("icon-change");
}, 300);
}
video.addEventListener("play", toggleButton);
video.addEventListener("pause", toggleButton);
數icon
,如果video為暫停狀態輸出字串 "►" 否則"❚ ❚"toggle.textContent =icon
,如果icon 是"►”,將 textContent改為 "►”"play"
及"pause"
時,調用toggleButton,即在暫停或播放時將icon改成對應的字串function skip() {
video.currentTime += parseFloat(this.dataset.skip);
}
skipButtons.forEach((buttons) => buttons.addEventListener("click", skip));
因為skipButtons為[data-skip]類的按鈕元素的** NodeList**,所以我們必需為每個按鈕添加一個事件監聽器,而forEach是一個非常方便的方法
流程為:
抓取每一個按鈕⇒為每個按鈕添加監聽器⇒觀察哪個按鈕被點擊⇒調用skip函式
this.dataset.skip
:dataset為我們自己在html設定的data-* attribute(自訂 data 屬性),分別設置的數值為data-skip="-10”、data-skip="25”,而我們取的是data-skip內的value
當我們監聽到click
事件時,運行video.currentTime += parseFloat(this.dataset.skip)
,即video的當前時間+當前點擊的按鈕的data-skip的值
function handleRangeUpdate() {
video[this.name] = this.value;
}
ranges.forEach((slider) => {
slider.addEventListener("change", handleRangeUpdate);
});
ranges.forEach((slider) => {
slider.addEventListener("mousemove", handleRangeUpdate);
});
我們分別設置的input
的name為volume、playbackRate還有value的預設值
this.value
代表了當前滑桿(或其他控件)的值,這是用來動態調整 video 元素的某些屬性(例如音量、播放速度等)
在監聽到"change"(改變)
以及"mousemove(滑鼠移動)
之後調動函式
function handleProgress() {
const percent = (video.currentTime / video.duration) * 100;
progressBar.style.flexBasis = `${percent}%`;}
video.addEventListener("timeupdate", handleProgress); *//隨著時間更新進度條*
設定變數percent
算出當前時間/總時長的百分比
更改**flexBasis的%**數達到自動伸展的效果
video.addEventListener("timeupdate")
為監聽到影片時間更新並調動函式
function scrub(e) {
const scrubTime = (e.offsetX / progress.offsetWidth) * video.duration;
video.currentTime = scrubTime;
}
let mousedown = false;
progress.addEventListener("click", scrub); //點選進度條更新
progress.addEventListener("mousemove", (e) => mousedown && scrub(e));
progress.addEventListener("mousedown", () => (mousedown = true));
progress.addEventListener("mouseup", () => (mousedown = false));
scrubTime = (e.offsetX / progress.offsetWidth) * video.duration;
這是在計算當進度條在offsetX位置時,在progress總寬的比例對應的影片時間mousedown
變數用來確保只有在按住鼠標並拖動時,mousemove 事件才會更新影片時間。這避免了在不按住鼠標時移動鼠標導致影片自動拖動。mousedown && scrub(e)
為如果mousedown 為真,則調動 scrub(e)
const method = video.paused ? "play" : "pause";
video[method]();
video.method()
這種方法呼叫方式的好處是,它可以在運行時期動態地決定要調用的方法(e) => mousedown && scrub(e)
這段扣是運用短路求值的語法,如果左邊的操作數 (mousedown) 為 true,那麼它會繼續執行右邊的操作 (scrub(e))。 如果左邊的操作數為 false,那麼整個表達式立即返回 false,右邊的操作就不會執行。
[ Alex 宅幹嘛 ] 👨💻 深入淺出 Javascript30 快速導覽 | Day 11:Custom Video Player
JS30