行业知识
30天JS挑战(第十一天)-------JS原生实现视频控制
2026-11-04 05:59:26
来源:互联网转载
第十一天挑战(视频控制)
地址:https://javascript30.com/
所有内容均上传至gitee,答案不唯一,仅代表本人思路
中文详解:https://github.com/soyaine/JavaScript30
该详解是Soyaine及其团队整理编撰的,是对源代码的详解,强烈推荐大家观看学习!!!
本人gitee:https://gitee.com/thats-all-right-ha-ha/30-days—js-challenge
效果
-
样式分析
- 组件总共分两个部分,首先是视频主体部分
- 其次是控制部分,控制部分也分为两个部分,一个是视频进度条另一个是视频控件
-
逻辑分析
-
点击视频后视频开始播放和暂停,并且下方控制按钮根据视频状态切换
-
进度条根据视频进度进行对应,拖动和点击进度条可以控制视频的进度
-
左侧range条可以控制音量的大小(点击或拖动)
-
右侧range条可以控制视频的倍速(点击或拖动)
-
右侧控件可以根据对应的值对视频进行快进或快退
本人代码及思路分析
仅提供布局及逻辑代码
结构:
► « 10s 25s »
逻辑:
const player = document.querySelector('.player')const toggle = document.querySelector('.toggle')const volume = document.querySelector('[name="volume"]')const playbackRate = document.querySelector('[name="playbackRate"]')const skipButton = document.querySelectorAll('[data-skip]')const view = document.querySelector('.viewer')const progressFilled = document.querySelector('.progress__filled')const progress = document.querySelector('.progress')let isClick = false//视频播放开关function viewSwitch(){ view.paused ? view.play() : view.pause() }//播放图片切换function iconChange() { const icon = this.paused ? '►' : '❚ ❚'; toggle.textContent = icon}//视频快进/快退function skip() { console.log(view.currentTime) view.currentTime += ~~this.dataset.skip}//视频倍速function videoRate(e){ view.playbackRate = e.target.value}//添加声音function videoVolume(e){ view.volume = e.target.value}//进度条function progressBar(){ const nowLoding = view.currentTime / view.duration progressFilled.style.flexBasis = `${nowLoding * 100}%`}//控制进度条function changeProgressBar(e){ const nowWidth = e.offsetX / progress.offsetWidth view.currentTime = view.duration * nowWidth}//视频控制view.addEventListener('click',viewSwitch)view.addEventListener('play', iconChange)view.addEventListener('pause',iconChange)view.addEventListener('timeupdate',progressBar)//播放按钮控制toggle.addEventListener('click',viewSwitch)//快进快退skipButton.forEach(element => { element.addEventListener('click',skip)});//视频倍速playbackRate.addEventListener('input',videoRate)//视频音量volume.addEventListener('input',videoVolume)//拖动控制条progress.addEventListener('click',changeProgressBar)progress.addEventListener('mousedown', () => { isClick = true})progress.addEventListener('mousemove', (e) => { if(isClick){ changeProgressBar(e) }})progress.addEventListener('mouseup', () => { isClick = false})分析:
-
**整体思路:**获取所有需要添加事件的元素,并且添加事件,通过控制视频的属性来控制视频的播放,通过range的值更改视频的音量和倍速
-
具体实现:
- viewSwitch:通过paused属性判断当前的视频播放状态(paused返回布尔值)
- iconChange:通过paused属性判断当前视频的播放状态,根据当前视频状态更改控件样式
- skip:通过currentTime控制当前视频的进度,利用dataset获取标签上对应的自定义值,让其相加实现快进/快退效果(dataset标签上的值是字符类型,需要先进行转换)
- videoRate:获取range标签的值,通过playbackRate更改视频的倍速,
- videoVolume:获取range标签的值,通过volume更改视频的音量
- progressBar:通过currentTime获取当前的时长,通过duration获取总视频的时长,让其相除,获取比例 *100更改进度条的百分比
- changeProgressBar:通过offsetX获取当前鼠标点击的值,通过offsetWidth获取进度条总长度,让其相除获得比例,通过比例更改视频进度
- 监听视频的 点击、开始、暂停、进度更改事件,并根据事件执行对应函数
-
弊端分析(与官方方法对比):
- mousemove事件仅作用于进度条内,如果移动的过程中鼠标脱离出了该范围,则会失效
官方代码
官方代码仅代表该案例原作者思路,不唯一
结构
► « 10s 25s »
逻辑
/* Get Our Elements */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('[data-skip]');const ranges = player.querySelectorAll('.player__slider');/* Build out functions */function togglePlay() { const method = video.paused ? 'play' : 'pause'; video[method]();}function updateButton() { const icon = this.paused ? '►' : '❚ ❚'; console.log(icon); toggle.textContent = icon;}function skip() { video.currentTime += parseFloat(this.dataset.skip);}function handleRangeUpdate() { video[this.name] = this.value;}function handleProgress() { const percent = (video.currentTime / video.duration) * 100; progressBar.style.flexBasis = `${percent}%`;}function scrub(e) { const scrubTime = (e.offsetX / progress.offsetWidth) * video.duration; video.currentTime = scrubTime;}/* Hook up the event listeners */video.addEventListener('click', togglePlay);video.addEventListener('play', updateButton);video.addEventListener('pause', updateButton);video.addEventListener('timeupdate', handleProgress);toggle.addEventListener('click', togglePlay);skipButtons.forEach(button => button.addEventListener('click', skip));ranges.forEach(range => range.addEventListener('change', handleRangeUpdate));ranges.forEach(range => range.addEventListener('mousemove', handleRangeUpdate));let mousedown = false;progress.addEventListener('click', scrub);progress.addEventListener('mousemove', (e) => mousedown && scrub(e));progress.addEventListener('mousedown', () => mousedown = true);progress.addEventListener('mouseup', () => mousedown = false);建议直接去看Soyaine的中文详解
- mousemove事件仅作用于进度条内,如果移动的过程中鼠标脱离出了该范围,则会失效
-
-
下一篇:会员服务器怎么关闭?