iT邦幫忙

2021 iThome 鐵人賽

DAY 28
1
自我挑戰組

JS30 學習日記系列 第 28

Day 28 - Build a Experimental Video Speed Controller UI

  • 分享至 

  • xImage
  •  

前言

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) }}
直播中

尚未有邦友留言

立即登入留言