整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

Angular 中自定义 Video 操作

Angular 中自定义 Video 操作

头条创作挑战赛#

本文同步本人掘金平台的文章:https://juejin.cn/post/7084784818247958535

上一篇文章是 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>
复制代码

这里使用了 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
}
复制代码

这里自定义的 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 获取。

【完】?

篇介绍了前端入门——html 中如何使用图片,今天讲下如何使用视频和音频等多媒体元素,它们能让你的网页更加丰富,读者相对于文字图片更愿意观看视频和音频或其它多媒体。在本教程中,您将了解到不同的多媒体格式,以及如何在您的网页中使用它们。

什么是多媒体?

是多种媒体的综合,一般包括文本,声音和图像等多种媒体形式。在计算机系统中,多媒体指组合两种或两种以上媒体的一种人机交互式信息交流和传播媒体。使用的媒体包括文字、图片、照片、声音、动画和影片,以及程式所提供的互动功能。

在因特网上,您会经常发现嵌入网页中的多媒体元素,现代浏览器已支持多种多媒体格式。

多媒体文件格式

多媒体元素(比如视频和音频)存储于媒体文件中。多媒体元素也拥有带有不同扩展名字的文件格式,比如 .swf、.wmv、.mp3 以及 .mp4。具体有哪些格式可以参考 w3cshool 网站的介绍,https://www.w3cschool.cn/html5/html5-video.html ,https://www.w3cschool.cn/html5/html5-audio.html。

HTML5 Video(视频)

直到现在,网页上仍然不存在一项显示视频的标准。今天,大多数视频是通过插件(比如 Flash)来显示的。然而,并非所有浏览器都拥有同样的插件。HTML5 规定了一种通过 video 元素来包含视频的标准方法。

语法如下:

<video width="320" height="240" controls>
  <source src="movie.mp4" type="video/mp4">
  <source src="movie.ogg" type="video/ogg">
  您的浏览器不支持Video标签。
</video>

<video> 元素提供了播放、暂停和音量控件来控制视频。

同时 <video> 元素也提供了 width 和 height 属性控制视频的尺寸。如果设置的高度和宽度,所需的视频空间会在页面加载时保留。如果没有设置这些属性,浏览器不知道视频的大小,浏览器就不能在加载时保留特定的空间,页面就会根据原始视频的大小而改变。

<video> 与 </video> 标签之间插入的内容是提供给不支持 video 元素的浏览器显示的。元素可以链接不同的视频文件。浏览器将使用第一个可识别的格式。一个页面可以使用多个<video> 标签,<video> 元素支持三种视频格式: MP4, WebM, 和 Ogg。

显示效果:

HTML5Audio(音频)

和视频一样没有统一的标准,各个浏览器都不一样。HTML5 规定了在网页上嵌入音频元素的标准,即使用 <audio> 元素。通过使用HTML5中的audio功能,你可以实现与flash相同的功能,即回放、跳转、缓冲等。

语法如下:

<audio controls>
  <source src="horse.ogg" type="audio/ogg">
  <source src="horse.mp3" type="audio/mpeg">
  您的浏览器不支持 audio 元素。
</audio>

control 属性供添加播放、暂停和音量控件。在<audio> 与 </audio> 之间你需要插入浏览器不支持的<audio>元素的提示文本 。允许使用多个 <source> 元素。<source> 元素可以链接不同的音频文件,浏览器将使用第一个支持的音频文件。目前, <audio>元素支持三种音频格式文件: MP3, Wav, 和 Ogg。

显示效果:

HTML 插件——辅助应用程序

插件(Plug-in)是扩展浏览器标准功能的计算机程序,插件被设计用于许多不同的目的:

  • 运行 Java 小程序
  • 运行 ActiveX 控件
  • 显示 Flash 电影
  • 显示视频或音频
  • 显示地图
  • 扫描病毒
  • 验证银行账号

1、<object> 元素

<object> 元素定义 HTML 文档中的嵌入式对象。

它旨在将插件(例如 Java applet、PDF 阅读器和 Flash 播放器)嵌入网页中,但也可以用于将 HTML 包含在 HTML 中。

如下:

插入一个网页片段

<object width="100%" height="500px" data="snippet.html"></object>

或者插入一个图片

<object data="audi.jpeg"></object>

播放一个视频

<object width="420" height="360"
classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B"
codebase="http://www.apple.com/qtactivex/qtplugin.cab">
<param name="src" value="movie.mp4">
<param name="controller" value="true">
</object>

播放一个音频

<object height="100" width="100" data="song.mp3"></object>

2、<embed> 元素

<embed> 元素也可定义了 HTML 文档中的嵌入式对象。这是一个 HTML5 标签,在 HTML4 中是非法的,但是所有浏览器中都有效。

插入一个flash文件

<embed width="400" height="50" src="bookmark.swf">

插入html片段

<embed width="100%" height="500px" src="snippet.html">

播放一个音频

<embed height="100" width="100" src="song.mp3" />

插入一个图片

<embed src="audi.jpeg">

注意:

大多数浏览器不再支持 Java 小程序和插件。

大多数现代浏览器关闭了对 Flash 的支持。

我们可以使用 <video> 和 <audio> 标签来显示视频和音频

视频和音频如何兼容大多浏览器

如下视频代码HTML 5 <video> 元素会尝试播放以 mp4、ogg 或 webm 格式中的一种来播放视频。如果均失败,则回退到 <embed> 元素。

HTML 5 + <object> + <embed> 是最好的解决办法。

<video width="320" height="240" controls="controls">
  <source src="movie.mp4" type="video/mp4" />
  <source src="movie.ogg" type="video/ogg" />
  <source src="movie.webm" type="video/webm" />
  <object data="movie.mp4" width="320" height="240">
    <embed src="movie.swf" width="320" height="240" />
  </object>
</video>

如下音频代码HTML5 <audio> 元素会尝试以 mp3 或 ogg 来播放音频。如果失败,代码将回退尝试 <embed> 元素。

HTML 5 + <embed> 是最好的解决办法。

<audio controls="controls" height="100" width="100">
  <source src="song.mp3" type="audio/mp3" />
  <source src="song.ogg" type="audio/ogg" />
  <embed height="100" width="100" src="song.mp3" />
</audio>

到此你以及了解了如何在网页中使用视频音频及其它多媒体控件,赶快自己试试,祝你学习愉快。

参考文献:https://www.w3school.com.cn/html/html_video.asp

上篇:前端入门——html 中如何使用图片

下篇:前端入门——html 表格的使用

网页开发中,跟踪用户与多媒体内容(如视频)的互动是一项常见需求。无论是教育平台、数据分析,还是用户参与度统计,监控用户如何观看视频内容都能提供宝贵的见解。这篇文章将探索如何使用JavaScript实现视频播放时长的跟踪。

目标

我们的目标是跟踪用户观看视频的总时长,包括暂停的时间,并将这些信息更新到后台系统。我们将通过捕获播放、暂停和结束等事件来计算观看时间。

实现步骤

让我们来分解一下实现的关键方面:

1. HTML结构

我们将使用HTML5的<video>标签将视频嵌入到网页中。每个视频元素都将有一个唯一的标识符,以便在JavaScript中轻松访问。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>视频播放时长跟踪</title>
  </head>
  <body>
    <!-- 视频容器 -->
    <video id="video_content1" width="640" height="360" controls>
      <!-- 视频源 -->
      <source src="your_video_source.mp4" type="video/mp4" />
    </video>

    <!-- 包含JavaScript代码 -->
    <script src="your_script.js"></script>
  </body>
</html>

2. JavaScript实现

在JavaScript文件(your_script.js)中,我们将处理视频事件并计算总的观看时间。

// 获取视频元素
let videoMat="your_video_source.mp4";
let source=document.createElement('source');
let video=document.getElementById('video_content1');

// 设置视频源
source.src=videoMat;
source.type='video/mp4';

// 将源附加到视频元素
if (video) {
  video.appendChild(source);

  // 初始化变量
  let startTime=null;
  let lastUpdateTime=null;
  let totalElapsedTime=0;

  // 'play'事件监听器
  video.addEventListener('play', function () {
    startTime=new Date();
    lastUpdateTime=startTime;
    console.log('视频正在播放。开始时间:', startTime);
  });

  // 'timeupdate'事件监听器
  video.addEventListener('timeupdate', function () {
    if (!video.paused && startTime !==null) {
      const currentTime=new Date();
      const elapsedSinceLastUpdate=(currentTime - lastUpdateTime) / 1000;
      totalElapsedTime +=elapsedSinceLastUpdate;
      lastUpdateTime=currentTime;
      console.log("从开始到现在的观看时间: " + totalElapsedTime + " 秒");
    }
  });

  // 'pause'事件监听器
  video.addEventListener('pause', function () {
    // 仅当视频已在播放时存储暂停时间
    if (startTime !==null) {
      const pausedTime=video.currentTime;
      console.log('视频已暂停。暂停时刻:', pausedTime);
      checkAndUpdateItem(totalElapsedTime, 1, 'your_video_title');
    }
  });

  // 'ended'事件监听器
  video.addEventListener('ended', function () {
    // 视频播放已结束
    checkAndUpdateItem(totalElapsedTime, 1, 'your_video_title');
  });

  // 'play'事件监听器(从暂停时间继续播放)
  video.addEventListener('play', function () {
    // 如果视频之前暂停,继续从暂停时刻播放
    if (startTime !==null) {
      video.currentTime=video.currentTime;
    }
  });
}

解释

  1. HTML结构:我们使用<video>标签嵌入视频,并提供一个唯一标识符(video_content1)以便在JavaScript中访问。我们在body末尾包含JavaScript文件,以确保DOM加载完成后再运行脚本。
  2. JavaScript实现
  • 我们动态设置视频源。
  • 设置了播放、时间更新、暂停和结束事件的监听器。
  • 在‘play’事件中,我们捕获开始时间和最后更新时间。
  • 在‘timeupdate’事件中,我们不断计算自上次更新以来的观看时间。
  • 视频暂停时,我们存储暂停时间并更新后台。
  • ‘ended’事件表示视频播放结束。

结论

实现视频播放时长的跟踪可以增强用户分析,提供有关用户参与度和内容受欢迎程度的见解。这里提供的JavaScript代码为您集成视频跟踪到网页应用中提供了基础。

记得将‘your_video_source.mp4’‘your_video_title’替换为实际的视频源和标题。

祝您编码愉快!