We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第10天,点击查看活动详情
上一篇文章是 Angular 项目实现权限控制。最近自己在网上看到别人使用 vue 进行自定义 video 的操纵。加上不久前实现了 angular 自定义 video 的相关需求, 遂来记录一下,作为交流思考🤔
vue
video
angular
实现的功能如下:
如图:
下面我们来一一实现:
这里的重点不在布局,我们简单来定义一下:
<!-- app.component.html --> <div class="video-page"> <div class="video-tools"> <button nz-button nzType="primary" (click)="play('btn')" style="margin-right: 12px;">播放 ✅</button> <button nz-button nzType="primary" (click)="pause('btn')">暂停 ✅</button> <ng-container> <button nz-button nz-dropdown [nzDropdownMenu]="menuForward" nzPlacement="bottomCenter" style="margin: 0 12px;">快进 ✅</button> <nz-dropdown-menu #menuForward="nzDropdownMenu"> <ul nz-menu> <li nz-menu-item (click)="forwardSecond(10)">快进 10 s</li> <li nz-menu-item (click)="forwardSecond(20)">快进 20 s</li> </ul> </nz-dropdown-menu> </ng-container> <ng-container> <button nz-button nz-dropdown [nzDropdownMenu]="menuBack" nzPlacement="bottomCenter">快退 ✅</button> <nz-dropdown-menu #menuBack="nzDropdownMenu"> <ul nz-menu> <li nz-menu-item (click)="retreatSecond(10)">快退 10 s</li> <li nz-menu-item (click)="retreatSecond(20)">快退 20 s</li> </ul> </nz-dropdown-menu> </ng-container> <ng-container> <button nz-button nz-dropdown [nzDropdownMenu]="speedUp" nzPlacement="bottomCenter" style="margin: 0 12px;">倍速 ✅</button> <nz-dropdown-menu #speedUp="nzDropdownMenu"> <ul nz-menu> <li nz-menu-item (click)="speedUpVideo(1)">正常</li> <li nz-menu-item (click)="speedUpVideo(2)">2 倍</li> <li nz-menu-item (click)="speedUpVideo(4)">4 倍</li> </ul> </nz-dropdown-menu> </ng-container> <button nz-button nzType="primary" (click)="openOrCloseVoice()">声音开 / 声音关 ✅</button> <button nz-button nzType="primary" style="margin: 0 12px;" (click)="toFullScreen()">全屏 ✅</button> <br /> <button nz-button nzType="primary" style="margin-top: 12px;" (click)="entryInPicture()">进入画中画 ⚠️ 安卓平板不支持</button> <button nz-button nzType="primary" style="margin: 12px 12px 0 12px;" (click)="exitInPicture()">退出画中画 ⚠️ 安卓平板不支持</button> <br /> <div style="display: flex; justify-content: flex-start; align-items: center; margin: 12px 0;"> 经过时长 / 总时长 : ✅ {{ currentTime }} / {{ totalTime }} </div> <!-- 进度条 --> <div style="display: flex; justify-content: flex-start; align-items: center; margin: 12px 0;"> 进度条:✅ <div class="custom-video_control-bg" (mousedown)="handleProgressDown($event)" (mousemove)="handleProgressMove($event)" (mouseup)="handleProgressUp($event)" > <div class="custom-video_control-bg-outside" id="custom-video_control-bg-outside" > <span class="custom-video_control-bg-inside" id="custom-video_control-bg-inside" ></span> <span class="custom-video_control-bg-inside-point" id="custom-video_control-bg-inside-point" ></span> </div> </div> </div> <div style="display: flex; justify-content: flex-start; align-items: center; margin: 12px 0;"> 声音条:✅ <div class="custom-video_control-voice"> <span class="custom-video_control-voice-play"> <i nz-icon nzType="sound" nzTheme="outline"></i> </span> <div class="custom-video_control-voice-bg" id="custom-video_control-voice-bg" (mousedown)="handleVolProgressDown($event)" (mousemove)="handleVolProgressMove($event)" (mouseup)="handleVolProgressUp($event)" > <div class="custom-video_control-voice-bg-outside" id="custom-video_control-voice-bg-outside" > <span class="custom-video_control-voice-bg-inside" id="custom-video_control-voice-bg-inside" ></span> <span class="custom-video_control-voice-bg-point" id="custom-video_control-voice-bg-point" ></span> </div> </div> </div> </div> </div> <div class="video-content"> <video id="video" class="video" style="width: 100%" poster="assets/poster.png"> <source type="video/mp4" src="assets/demo.mp4"> Sorry, your browser doesn't support. </video> </div> </div>
这里使用了 angular ant design,之前写了一篇相关文章,还不熟悉的读者可前往 Angular 结合 NG-ZORRO 快速开发
angular ant design
这里直接调用 video 对象的方法 play() 和 pause():
play()
pause()
// app.component.ts // 播放按钮事件 play(flag: string | undefined) { if(flag) this.videoState.playState = true this.videoState.play = true this.video.play() } // 暂停按钮事件 pause(flag: string | undefined): void { if(flag) this.videoState.playState = false this.video.pause() this.videoState.play = false }
这里自定义的 play 和 pause 方法加上了一个标志,对下下面要讲的进度条的控制有帮助,上面的代码可以更加简洁,读者可以简写下。
play
pause
这里的快退,快进和倍速设置了不同的选项,通过参数进行传递:
// app.component.ts // 快进指定的时间 forwardSecond(second: number): void { this.video.currentTime += second; // 定位到当前的播放时间 currentTime } // 后退指定的时间 retreatSecond(second: number): void { this.video.currentTime -= second } // 倍速 speedUpVideo(multiple: number): void { this.video.playbackRate = multiple; // 设定当前的倍速 playbackRate }
声音的开关使用 video 的 muted 属性即可:
muted
// app.component.ts // 开或关声音 openOrCloseVoice(): void { this.video.muted = !this.video.muted; }
全屏的操作也是很简单,使用 webkitRequestFullScreen
webkitRequestFullScreen
// app.component.ts // 全屏操作 toFullScreen(): void { this.video.webkitRequestFullScreen() }
全屏后,按 esc 可退出全屏
esc
画中画相当于弹窗缩小视频~
// app.component.ts // 进入画中画 entryInPicture(): void { this.video.requestPictureInPicture() this.video.style.display = "none" } // 退出画中画 exitInPicture(): void { if(this.document.pictureInPictureElement) { this.document.exitPictureInPicture() this.video.style.display = "block" } }
设置 video 的样式,是为了看起来不突兀...
记录视频的总时长和视频当前的播放时长。我们已经来组件的时候就获取视频的元信息,得到总时长;在视频播放的过程中,更新当前时长。
// app.component.ts // 初始化 video 的相关的事件 initVideoData(): void { // 获取视频的总时长 this.video.addEventListener('loadedmetadata', () => { this.totalTime = this.formatTime(this.video.duration) }) // 监听时间发生更改 this.video.addEventListener('timeupdate', () => { this.currentTime = this.formatTime(this.video.currentTime) // 当前播放的时间 }) }
formatTime 是格式化函数
监听鼠标的点击,移动,松开的事件,对视频的播放时间和总事件进行相除,计算百分比。
// app.component.ts // 进度条鼠标按下 handleProgressDown(event: any): void { this.videoState.downState = true this.pause(undefined); this.videoState.distance = event.clientX + document.documentElement.scrollLeft - this.videoState.leftInit; } // 进度条 滚动条移动 handleProgressMove(event: any): void { if(!this.videoState.downState) return let distanceX = (event.clientX + document.documentElement.scrollLeft) - this.videoState.leftInit if(distanceX > this.processWidth) { // 容错处理 distanceX = this.processWidth; } if(distanceX < 0) { // 容错处理 distanceX = 0 } this.videoState.distance = distanceX this.video.currentTime = this.videoState.distance / this.processWidth * this.video.duration } // 进度条 鼠标抬起 handleProgressUp(event: any): void { this.videoState.downState = false // 视频播放 this.video.currentTime = this.videoState.distance / this.processWidth * this.video.duration this.currentTime = this.formatTime(this.video.currentTime) if(this.videoState.playState) { this.play(undefined) } }
这里需要计算进度条的位置,来获取点击进度条的百分比,之后更新视频的当前播放时间。当然,我们还得有容错处理,比如进度条为负数时候,当前播放时间为0。
我们实现了播放进度条的操作,对声音进度条的实现就很容易上手了。声音进度条也是监听鼠标的点击,移动,松开。不过,这次我们处理的是已知声音 div 的高度。
div
// app.component.ts // 声音条 鼠标按下 handleVolProgressDown(event: any) { this.voiceState.topInit = this.getOffset(this.voiceProOut, undefined).top this.volProcessHeight = this.voiceProOut.clientHeight this.voiceState.downState = true //按下鼠标标志 this.voiceState.distance = this.volProcessHeight - (event.clientY + document.documentElement.scrollTop - this.voiceState.topInit) } // 声音 滚动条移动 handleVolProgressMove(event: any) { if(!this.voiceState.downState) return let disY = this.voiceState.topInit + this.volProcessHeight - (event.clientY + document.documentElement.scrollTop) if(disY > this.volProcessHeight - 2) { // 容错处理 disY = this.volProcessHeight - 2 } if(disY < 0) { // 容错处理 disY = 0 } this.voiceState.distance = disY this.video.volume = this.voiceState.distance / this.volProcessHeight this.videoOption.volume = Math.round(this.video.volume * 100) } // 声音 鼠标抬起 handleVolProgressUp(event: any) { this.voiceState.downState = false //按下鼠标标志 let voiceRate = this.voiceState.distance / this.volProcessHeight if(voiceRate > 1) { voiceRate = 1 } if(voiceRate < 0) { voiceRate = 0 } this.video.volume = voiceRate this.videoOption.volume = Math.round(this.video.volume * 100); // 赋值给视频声音 }
完成了上面的内容,我们以一个 gif 图来展示效果:
gif
全屏,声音和画中画比较难截图,Gif 上体现不来
Gif
详细的代码,请前往 video-ng 获取。
【完】✅
The text was updated successfully, but these errors were encountered:
No branches or pull requests
一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第10天,点击查看活动详情
上一篇文章是 Angular 项目实现权限控制。最近自己在网上看到别人使用
vue
进行自定义video
的操纵。加上不久前实现了angular
自定义video
的相关需求, 遂来记录一下,作为交流思考🤔实现的功能如下:
如图:
下面我们来一一实现:
这里的重点不在布局,我们简单来定义一下:
播放 / 停止
这里直接调用
video
对象的方法play()
和pause()
:这里自定义的
play
和pause
方法加上了一个标志,对下下面要讲的进度条的控制有帮助,上面的代码可以更加简洁,读者可以简写下。快退 / 快进 / 倍速
这里的快退,快进和倍速设置了不同的选项,通过参数进行传递:
声音开 / 声音关
声音的开关使用
video
的muted
属性即可:进入全屏 / 退出全屏
全屏的操作也是很简单,使用
webkitRequestFullScreen
进入画中画 / 退出画中画
画中画相当于弹窗缩小视频~
设置
video
的样式,是为了看起来不突兀...经过时长 / 总时长
记录视频的总时长和视频当前的播放时长。我们已经来组件的时候就获取视频的元信息,得到总时长;在视频播放的过程中,更新当前时长。
播放进度条功能
监听鼠标的点击,移动,松开的事件,对视频的播放时间和总事件进行相除,计算百分比。
这里需要计算进度条的位置,来获取点击进度条的百分比,之后更新视频的当前播放时间。当然,我们还得有容错处理,比如进度条为负数时候,当前播放时间为0。
声音进度条
我们实现了播放进度条的操作,对声音进度条的实现就很容易上手了。声音进度条也是监听鼠标的点击,移动,松开。不过,这次我们处理的是已知声音
div
的高度。如图:
效果演示
完成了上面的内容,我们以一个
gif
图来展示效果:详细的代码,请前往 video-ng 获取。
【完】✅
The text was updated successfully, but these errors were encountered: