封装一个支持长按屏幕选择加速倍率的视频组件

说在前面

在短视频兴起的时代,很多的视频软件都有视频加速的功能,只需轻轻长按屏幕,视频便会根据预设的速度模式进行倍速播放,这是很常用而且很实用的一个功能,今天就让我们来简单实现一个组件,支持长按屏幕加速,且可以滑动选择加速倍率。

效果展示

pc端

移动端

体验地址

jyeontu.xyz/jvuewheel/#…

组件实现

1、组件属性(props)

width

视频播放器的宽度,可传入如 "300px""50%" 等合法的 CSS 宽度值。默认值为"300px"

height

视频播放器的高度,接受合法的 CSS 高度值。默认为"200px"

videoUrl

视频的源地址,需为有效的视频文件 URL,本地视频或线上链接都行。

 

javascript

代码解读

复制代码

videoUrl: require("../../assets/video/密码箱.mp4"), videoUrl: "http://jyeontu.xyz/video/202112250058.mp4",

loop

是否循环播放视频,默认为false

timeIntervalLimit

长按事件的时间间隔限制(单位:毫秒),用于判断长按操作的触发条件,默认为1500,即长按屏幕1.5就会触发长按加速事件。

speedChooseList

可选的播放速度列表,数组元素为数字,表示倍速,默认为 [2, 3, 4]

2、获取video位置尺寸

获取视频元素和组件容器的位置和尺寸信息,存储在 videoContentInfo 中,用于后续的长按位置计算和速度调节。

 

javascript

代码解读

复制代码

initVideoContentInfo() { const JVideoSpeedBox = this.$refs[this.uid + "-JVideoSpeed"]; const videoContent = this.$refs[this.uid + "-video"]; const videoContentInfo = { offSetTop: videoContent.offsetTop || JVideoSpeedBox.offsetTop, offsetLeft: videoContent.offsetLeft || JVideoSpeedBox.offsetLeft, height: videoContent.offsetHeight || JVideoSpeedBox.offsetHeight, width: videoContent.offsetWidth || JVideoSpeedBox.offsetWidth, }; this.videoContentInfo = videoContentInfo; },

3、video点击事件

处理视频的点击事件,实际上调用 videoMouseUp 方法,用于统一处理视频播放状态的切换逻辑,避免在点击和其他操作(如长按后松开)时出现不一致的播放状态。

 

javascript

代码解读

复制代码

videoClick(e) { this.videoMouseUp(e); },

4、鼠标按下事件

处理鼠标按下事件,记录按下时间 downTime,并在 timeIntervalLimit 后判断是否为长按操作,如果视频未暂停,则执行 videoLongPress 方法展示速度选择面板并进行速度调节。

 

javascript

代码解读

复制代码

videoMouseDown(e) { this.downTime = new Date().getTime(); setTimeout(() => { const videoContent = this.$refs[this.uid + "-video"]; if (videoContent.paused) { this.downTime = null; return; } if (!this.downTime) return; this.videoLongPress(e); }, this.timeIntervalLimit); },

5、长按结束事件

在长按停止时,将播放速度恢复为正常速度(1 倍速),并在视频暂停时恢复播放,确保视频播放状态的正确切换和速度的正常恢复。

 

javascript

代码解读

复制代码

videoLongPressStop(e) { this.speedRate = 1; const target = e.target; if (target.className !== "j-video-speed-content") return; const videoContent = this.$refs[this.uid + "-video"]; setTimeout(() => { if (videoContent.paused) { videoContent.play(); } }, 50); },

6、选中速度设置

更新速度选择面板中当前选中速度选项的样式,通过添加或移除特定的类名(j-video-speed-rates-rate-acitvity)来实现视觉上的选中反馈,增强用户交互体验。如果获取元素失败,会尝试重新获取和更新样式,以应对可能的加载延迟或其他异常情况。

  • 参数
    • rate:要设置为选中状态的播放速度值,用于确定对应的速度选项元素并更新其样式。
    • times(可选):重试次数,默认为 1,用于递归调用时控制重试逻辑,避免无限循环。
 

javascript

代码解读

复制代码

videoSpeedRateTextChange(rate, times = 1) { try { const rateContents = document.getElementsByClassName( "j-video-speed-rates-rate-acitvity" ); for (const item of rateContents) { item.classList.remove("j-video-speed-rates-rate-acitvity"); } if (!this.speedChooseList.includes(rate)) return; const rateContent = this.$refs[this.uid + "speedRate" + rate][0]; rateContent.classList.add("j-video-speed-rates-rate-acitvity"); } catch (err) { if (!times) return; setTimeout(() => { this.videoSpeedRateTextChange(rate, times - 1); }, 100); } },

7、视频播放速度修改

直接设置视频的播放速度,通过修改视频元素的 playbackRate 属性来实现,并更新 speedRate 数据,以便组件内部记录和后续操作使用。

  • 参数
    • rate:要设置的播放速度值,需为数字类型,如 2、3 等,表示倍速。
 

javascript

代码解读

复制代码

videoSpeedRateChange(rate) { const videoContent = this.$refs[this.uid + "-video"]; videoContent.playbackRate = rate; this.speedRate = rate; },

8、视频长按事件

在长按视频时触发,展示速度选择面板(showRagePanel 设为 true),计算长按位置对应的播放速度值,并调用 videoSpeedRateChangevideoSpeedRateTextChange 方法来设置和显示选中的速度选项,实现快速的播放速度调节。

 

javascript

代码解读

复制代码

videoLongPress(e) { this.showRagePanel = true; const rate = this.calcSpeedRate(e); if (!rate) return; this.videoSpeedRateChange(rate); this.videoSpeedRateTextChange(rate); },

9、计算加速倍率

根据长按位置(layerY)和速度选择列表,计算出对应的播放速度值。如果长按位置超出视频区域或不符合计算条件,则返回 null。通过将长按位置与每个速度选项对应的区域高度进行比较,确定用户选择的速度值,为速度调节提供准确的数据支持。

 

javascript

代码解读

复制代码

calcSpeedRate(e) { const videoContentInfo = this.videoContentInfo; let layerY = e.layerY; if (!e.layerY && e.touches) { layerY = e.touches[0].pageY - videoContentInfo.offSetTop; } if (layerY < 0) return; const preSpeedRateHeight = videoContentInfo.height / this.speedChooseList.length; const speedRate = this.speedChooseList[Math.floor(layerY / preSpeedRateHeight)]; return speedRate; },

10、鼠标(触屏)移动事件

处理视频的移动事件(在长按过程中),根据时间间隔判断是否满足长按条件,如果满足则执行 videoLongPress 方法继续速度调节操作,确保在长按拖动过程中能实时响应速度变化。同时,通过 e.preventDefault() 阻止默认的滚动行为,避免页面滚动干扰视频操作。

 

javascript

代码解读

复制代码

videoMove(e) { if (!this.downTime) return; const videoContent = this.$refs[this.uid + "-video"]; if (videoContent.paused) { this.downTime = null; return; } e.preventDefault(); const nowTime = new Date().getTime(); const timeDif = nowTime - this.downTime; if (timeDif >= this.timeIntervalLimit) { this.videoLongPress(e); } },

11、切换视频的播放状态

长按结束后恢复视频原始播放状态,在一定延迟(50 毫秒)后切换视频的播放状态,即如果视频当前暂停,则恢复播放;如果正在播放,则暂停播放。通过 setTimeout 实现延迟操作,确保播放状态的切换在合适的时机进行,避免与其他操作冲突。

 

javascript

代码解读

复制代码

changeVideoPlayStaus() { const videoContent = this.$refs[this.uid + "-video"]; setTimeout(() => { if (videoContent.paused) { videoContent.play(); } else { videoContent.pause(); } }, 50); },

12、鼠标抬起(触屏结束)事件

处理鼠标松开事件,将播放速度恢复为正常速度(1 倍速),根据按下和松开的时间间隔判断是否为长按操作,如果是长按操作,则执行 videoLongPressStop 方法进行后续处理;否则,如果是触摸事件且时间间隔较短,则调用 changeVideoPlayStaus 方法切换视频播放状态。同时,隐藏速度选择面板(showRagePanel 设为 false),完成一次完整的视频操作交互流程。

 

javascript

代码解读

复制代码

videoMouseUp(e) { this.videoSpeedRateChange(1); if (!this.downTime) return; const upTime = new Date().getTime(); const timeDif = upTime - this.downTime; this.downTime = null; this.showRagePanel = false; if (timeDif >= this.timeIntervalLimit) { this.videoLongPressStop(e); return; } else { if (e.touches) this.changeVideoPlayStaus(); } },

组件使用

 

html

代码解读

复制代码

<template> <div class="content"> <div class="video-list"> <JVideoSpeed class="video" :videoUrl="videoUrl" videoWidth: "768px", videoHeight: "412px", :speedChooseList="speedChooseList" > </JVideoSpeed> </div> </div> </template> <script> export default { data() { return { videoUrl: require("../../assets/video/202112250058.mp4"), speedChooseList: [2, 3, 4, 5], videoWidth: "768px", videoHeight: "412px", } }, created() { this.initVideoBox(); }, methods:{ initVideoBox() { const videoWidth = parseInt(this.videoWidth); const videoHeight = parseInt(this.videoHeight); const rate = videoWidth / videoHeight; const width = window.innerWidth; const height = window.innerHeight; if (width < height) { this.videoWidth = width * 0.95 + "px"; this.videoHeight = (width * 0.95) / rate + "px"; } }, } } </script>

组件库

组件文档

目前该组件也已经收录到我的组件库,组件文档地址如下: jyeontu.xyz/jvuewheel/#…

组件内容

组件库中还有许多好玩有趣的组件,如:

  • 评论组件
  • 词云组件
  • 瀑布流照片容器
  • 视频动态封面
  • 3D轮播图
  • web桌宠
  • 贡献度面板
  • 拖拽上传
  • 自动补全输入框
  • 图片滑块验证

等等……

组件库源码

组件库已开源到gitee,有兴趣的也可以到这里看看:gitee.com/zheng_yongt…

🌟觉得有帮助的可以点个star~

🖊有什么问题或错误可以指出,欢迎pr~

📬有什么想要实现的组件或想法可以联系我~

公众号

关注公众号『前端也能这么有趣』,获取更多有趣内容。

发送『组件库』获取源码

说在后面

🎉 这里是 JYeontu,现在是一名前端工程师,有空会刷刷算法题,平时喜欢打羽毛球 🏸 ,平时也喜欢写些东西,既为自己记录 📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解 🙇,写错的地方望指出,定会认真改进 😊,偶尔也会在自己的公众号『前端也能这么有趣』发一些比较有趣的文章,有兴趣的也可以关注下。在此谢谢大家的支持,我们下文再见 🙌。

原文链接:https://juejin.cn/post/7448513468662743051

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值