今天要的题目是要来客製化一个影片播放器,做完之后,更加熟悉video的一些属性跟方法,如果不是有什么特别需求,我觉得controls (
),就很够用了。
完成品如下:
首先都获取我们会用到的元素
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 inputconst 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));// 对进度条增添事件,可利用鼠标移动进度到指定位置。// 判断是否按下鼠标,预设为falselet 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;}