JS30 全攻略 第28天

前言

JS 30 是由加拿大的全端工程師 Wes Bos 免費提供的 JavaScript 簡單應用課程,課程主打 No Frameworks、No Compilers、No Libraries、No Boilerplate 在30天的30部教學影片裡,建立30個JavaScript的有趣小東西。

另外,Wes Bos 也很無私地在 Github 上公開了所有 JS 30 課程的程式碼,有興趣的話可以去 fork 或下載。


本日目標

除了原本在video元素自帶的影片控制器(設定controls屬性),我們可以另外實作一個調節影片速度的控制介面,這個介面可以用拖拉的方式改變影片的播放速度。


解析程式碼

HTML 部分

div(.wrapper)是我們整個的影片播放器,下面可拆作兩部分,一個是 video(.flex)和自帶的預設控制介面(啟用controls),另一個是我們這次要實作出的影片速度調節介面 div(.speed)。

1
2
3
4
5
6
<div class="wrapper">
<video class="flex" width="765" height="430" src="http://clips.vorwaerts-gmbh.de/VfE_html5.mp4" loop controls></video>
<div class="speed">
<div class="speed-bar"></div>
</div>
</div>

JS 部分

首先,取得所有需要的元素 :

  • 宣告常數speed放入取得的速度調節介面(.speed)。
  • 宣告常數bar放入取得的速度調節介面內部的子元素(.speed-bar)。
  • 宣告常數video放入取得的video元素(.flex)。
1
2
3
const speed = document.querySelector('.speed');
const bar = document.querySelector('.speed-bar');
const video =document.querySelector('.flex');

speed註冊mousemove event listener監聽是否有滑鼠在speed上移動,有的話就用後方的function()作為event handler

event handler裡,我們要先取得的是滑鼠在內部移動時的 y 座標(e.pageY,相對整個 HTML 文件頂部而言),又因為我們無法保證速度調節介面(.speed)是在 HTML 文件的最頂端而且沒有marginpadding之類的,所以還須把取得的 y 座標減去.speed離視窗(offsetParent)頂端的距離(offsetTop)進行修正。

宣告常數percent算出目前滑鼠所在的 y 座標位置,相對於整個速度調節介面高度(this.offsetHeight)的比例,作為後續調整.speed-bar的高度和.flex影片播放速度的依據。

宣告常數maxmin作為調整影片播放速度時能達到的最大、最小倍率。

1
2
3
4
5
6
7
speed.addEventListener('mousemove', function(e){
//we can't assume that speed is on the top
const y = e.pageY - this.offsetTop;
const percent = y / this.offsetHeight;
const min = 0.4;
const max = 4;
});

宣告常數height,用Math.round(percent*100)+'%',將剛剛算出的比例換成百分比的形式。

宣告常數playbackRate計算現在的比例(percent)換算成的速度倍率。

.speed-bar的高度設為我們算出的高度百分比(height),然後再把它的文字內容換成現在的速度倍率(ex. 1.2x)。toFixed()幫我們把算出的速度倍率(playbackRate)取到小數點後1位。

最後修改videoplaybackRate屬性就完成了。

(播放速度太快或太慢均有可能導致影片部分聲音消失!!!)

1
2
3
4
5
6
7
8
speed.addEventListener('mousemove', function(e){
/*上略...*/
const height = Math.round(percent*100)+'%';
const playbackRate = percent * (max-min) + min;
bar.style.height = height;
bar.textContent = playbackRate.toFixed(1)+'x';
video.playbackRate = playbackRate;
});

補充資料 :

HTMLElement.offsetTop
HTMLMediaElement.playbackRate
HTMLElement.offsetHeight
Number.prototype.toFixed()
Math.round()

範例網頁請點此

觀看完整程式碼

分享到