• 技术文章 >web前端 >js教程

    Angular中怎么自定义视频播放器

    青灯夜游青灯夜游2022-05-11 21:13:54原创982
    怎么自定义 Video 操作?自定义视频播放器?下面本篇文章给大家介绍一下Angular 中自定义 Video 操作的方法,希望对大家有所帮助!

    上一篇文章是 Angular 项目实现权限控制。最近自己在网上看到别人使用 vue 进行自定义 video 的操作。加上不久前实现了 angular 自定义 video 的相关需求, 遂来记录一下,作为交流思考。【相关教程推荐:《angular教程》】

    实现的功能如下:

    如图:

    1.png

    下面我们来一一实现:

    这里的重点不在布局,我们简单来定义一下:

    <!-- 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 快速开发

    播放 / 停止

    这里直接调用 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
    }

    这里自定义的 playpause 方法加上了一个标志,对下下面要讲的进度条的控制有帮助,上面的代码可以更加简洁,读者可以简写下。

    快退 / 快进 / 倍速

    这里的快退,快进和倍速设置了不同的选项,通过参数进行传递:

    // 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
    }

    2.png

    声音开 / 声音关

    声音的开关使用 videomuted 属性即可:

    // 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); // 赋值给视频声音
    }

    如图:

    3.png

    效果演示

    完成了上面的内容,我们以一个 gif 图来展示效果:

    全屏,声音和画中画比较难截图,Gif 上体现不来

    详细的代码,请前往 video-ng 获取。

    【完】

    更多编程相关知识,请访问:编程入门!!

    以上就是Angular中怎么自定义视频播放器的详细内容,更多请关注php中文网其它相关文章!

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    专题推荐:Angular
    上一篇:聊聊V8的内存管理与垃圾回收算法 下一篇:浅析利用node怎么获取mac系统版本
    20期PHP线上班

    相关文章推荐

    • 【活动】充值PHP中文网VIP即送云服务器• Angular学习之以Tooltip为例了解自定义指令• 聊聊怎么利用Angular+Jenkins展示构建版本• Angular利用service实现自定义服务(notification)• 浅析Angular中怎么用 Api 代理• Angular如何对请求进行拦截封装?
    1/1

    PHP中文网