Angular中怎么自定义视频播放器
怎么自定义 Video 操作?自定义视频播放器?下面本篇文章给大家介绍一下Angular 中自定义 Video 操作的方法,希望对大家有所帮助!
上一篇文章是 Angular 项目实现权限控制。最近自己在网上看到别人使用 vue
进行自定义 video
的操作。加上不久前实现了 angular
自定义 video
的相关需求, 遂来记录一下,作为交流思考。
实现的功能如下:
播放 / 停止
快退 / 快进 / 倍速
声音开 / 声音关
进入全屏 / 退出全屏
进入画中画 / 退出画中画 【安卓平板不支持,不建议使用】
经过时长 / 总时长
播放进度条功能:支持点击,拖拽进度
声音进度条功能:支持点击,拖拽进度
如图:
下面我们来一一实现:
这里的重点不在布局,我们简单来定义一下:
- <!-- 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>
播放 / 停止
这里直接调用 video
对象的方法 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
方法加上了一个标志,对下下面要讲的进度条的控制有帮助,上面的代码可以更加简洁,读者可以简写下。
快退 / 快进 / 倍速
这里的快退,快进和倍速设置了不同的选项,通过参数进行传递:
- // 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
属性即可:
- // app.component.ts
- // 开或关声音
- openOrCloseVoice(): void {
- this.video.muted = !this.video.muted;
- }
进入全屏 / 退出全屏
全屏的操作也是很简单,使用 webkitRequestFullScreen
- // app.component.ts
- // 全屏操作
- toFullScreen(): void {
- this.video.webkitRequestFullScreen()
- }
全屏后,按 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
的高度。
- // 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
上体现不来
详细的代码,请前往 video-ng 获取。
本文网址:https://www.zztuku.com/index.php/detail-11792.html
站长图库 - Angular中怎么自定义视频播放器
申明:本文转载于《掘金社区》,如有侵犯,请 联系我们 删除。
您还没有登录,请 登录 后发表评论!
提示:请勿发布广告垃圾评论,否则封号处理!!