30天JS挑战(第十一天)-------JS原生实现视频控制

第十一天挑战(视频控制)

地址: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条可以控制视频的倍速(点击或拖动)

    • 右侧控件可以根据对应的值对视频进行快进或快退

本人代码及思路分析

仅提供布局及逻辑代码

结构:

html 复制代码
<div class="player">
  <video class="player__video viewer" src="652333414.mp4"></video>

  <div class="player__controls">
    <div class="progress">
      <div class="progress__filled"></div>
    </div>
    <button class="player__button toggle" title="Toggle Play">►</button>
    <input type="range" name="volume" class="player__slider" min="0" max="1" step="0.05" value="1">
    <input type="range" name="playbackRate" class="player__slider" min="0.5" max="2" step="0.1" value="1">
    <button data-skip="-10" class="player__button"><< 10s</button>
    <button data-skip="25" class="player__button">25s >></button>
  </div>
</div>

逻辑:

js 复制代码
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事件仅作用于进度条内,如果移动的过程中鼠标脱离出了该范围,则会失效

官方代码

官方代码仅代表该案例原作者思路,不唯一

结构

html 复制代码
<div class="player">
  <video class="player__video viewer" src="652333414.mp4"></video>

  <div class="player__controls">
    <div class="progress">
      <div class="progress__filled"></div>
    </div>
    <button class="player__button toggle" title="Toggle Play">►</button>
    <input type="range" name="volume" class="player__slider" min="0" max="1" step="0.05" value="1">
    <input type="range" name="playbackRate" class="player__slider" min="0.5" max="2" step="0.1" value="1">
    <button data-skip="-10" class="player__button"><< 10s</button>
    <button data-skip="25" class="player__button">25s >></button>
  </div>
</div>

逻辑

js 复制代码
/* 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的中文详解

相关推荐
爱写代码的刚子几秒前
C++知识总结
java·开发语言·c++
martian6651 分钟前
QT开发:基于Qt实现的交通信号灯模拟器:实现一个带有倒计时功能的图形界面应用
开发语言·qt
SEU-WYL3 分钟前
基于深度学习的视频摘要生成
人工智能·深度学习·音视频
冷琴19968 分钟前
基于java+springboot的酒店预定网站、酒店客房管理系统
java·开发语言·spring boot
PleaSure乐事14 分钟前
【Node.js】内置模块FileSystem的保姆级入门讲解
javascript·node.js·es6·filesystem
缘友一世16 分钟前
macOS .bash_profile配置文件优化记录
开发语言·macos·bash
tekin19 分钟前
macos 中使用macport安装,配置,切换多版本php,使用port 安装php扩展方法总结
开发语言·macos·php·port·mac多版本php安装管理·port-select
雷特IT24 分钟前
Uncaught TypeError: 0 is not a function的解决方法
前端·javascript
CSXB9928 分钟前
一、Python(介绍、环境搭建)
开发语言·python·测试工具·集成测试
火红的小辣椒38 分钟前
PHP反序列化7(字符串逃逸)
开发语言·web安全·php