iT邦幫忙

2021 iThome 鐵人賽

DAY 28
1
自我挑戰組

JS30 學習日記系列 第 28

Day 28 - Build a Experimental Video Speed Controller UI

前言

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

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


本日目標

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


解析程式碼

HTML 部分

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

<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">1×</div>
    </div>
</div>

JS 部分

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

  • 宣告常數speed放入取得的速度調節介面(.speed)。
  • 宣告常數bar放入取得的速度調節介面內部的子元素(.speed-bar)。
  • 宣告常數video放入取得的video元素(.flex)。
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作為調整影片播放速度時能達到的最大、最小倍率。

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屬性就完成了。

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

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()

範例網頁請點此

觀看完整程式碼


上一篇
Day 27 - Click and Drag to Scroll
下一篇
Day 29 - Vanilla JS Countdown Timer
系列文
JS30 學習日記31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言