手写一个简单的课程播放界面

581 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第8天,点击查看活动详情

前言

最近给一个学校做的项目,需求要有一个课程播放的功能。于是我就开始写了,说实话第一次接触视频播放之类的东西,心里不是特别有底。
温馨提示:作者水平一般写的不好,有需要改进的地方麻烦各位帮我指出来,评论区等你们。

需求

这里说一下这个页面大概的需求:

  • 课程列表是多级树形结构,不限制最高层级
  • 点击课程节点,播放当前节点视频,并且当前节点高亮
  • 视频资源加载完成后自动播放
  • 在视频加载完成之前,需要一个视频加载中动画
  • 点击课程卡片进入播放界面时,默认播放课程列表第一个
  • 点击课程节点进入播放界面时,播放该节点视频

开始

声明一下,这是个vue2+elementUI的项目,树形节点用 el-tree,视频播放用的是 video 标签,在这里还禁用了video自带的下载 controlsList="nodownload",禁用了画中画 disablePictureInPicture

<template>
  <div class="container" id="banRightBtn">
    <div class="header">{{ title }}</div>
    <div class="body">
      <div class="bd_left">
        <div class="title">
          {{ knowledgeBaseName }}
        </div>
        <div class="tree">
          <el-tree :data="data" node-key="id" :current-node-key="id" ref="tree" highlight-current
            :expand-on-click-node="false" :props="defaultProps" default-expand-all @node-click="handleNodeClick">
          </el-tree>
        </div>
      </div>
      <div class="bd_right" v-if="videourl">
        <div class="mask" v-if="!isReady">
          <div class="loader">
            <span>loading...</span>
          </div>
        </div>
        <video controls :src="videourl" controlsList="nodownload" disablePictureInPicture autoplay>
        </video>
      </div>
      <div class="bd_right" v-else>
        <div class="empty">
          <div>
            <img src="../../static/images/nodata.jpeg" alt="" srcset="">
            <div class="tips">敬请期待~</div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

节点高亮

获取到当前节点课程视频id后,用 setCurrentKey 设置节点高亮,前提是在 el-tree 中设置好当前高亮属性 highlight-current ,然后还要设置tree的key值 node-key="id",再设置当前节点id :current-node-key="id" 然后就可以赋值完成高亮,代码如下:

this.$refs.tree.setCurrentKey(this.id)

视频状态

获取视频状态,代码如下:

this.readyState = document.querySelector('video').readyState

表示音频/视频元素的就绪状态:

  • 0 = HAVE_NOTHING - 没有关于音频/视频是否就绪的信息
  • 1 = HAVE_METADATA - 关于音频/视频就绪的元数据
  • 2 = HAVE_CURRENT_DATA - 关于当前播放位置的数据是可用的,但没有足够的数据来播放下一帧/毫秒
  • 3 = HAVE_FUTURE_DATA - 当前及至少下一帧的数据是可用的
  • 4 = HAVE_ENOUGH_DATA - 可用数据足以开始播放

在视频没有加载完成之前,需要有一个炫酷的加载中动画

image.png 代码如下:

        <div class="mask" v-if="!isReady">
          <div class="loader">
            <span>loading...</span>
          </div>
        </div>
sass代码:
      .mask {
        position: absolute;
        width: calc(100vw - 402px);
        height: calc(100vh - 102px);
        background-color: #2c3e50;
        display: flex;
        justify-content: center;
        align-items: center;
        z-index: 9;
        font-family: 'Montserrat', sans-serif, Arial, 'Microsoft Yahei';

        .loader {
          position: relative;
          width: 100px;
          height: 100px;
          color: #fff;
          border-radius: 50%;
          border-top: 5px solid #fd79a8;
          border-bottom: 5px solid transparent;
          display: flex;
          justify-content: center;
          align-items: center;
          animation: animate .5s linear infinite;
        }

        .loader::after,
        .loader::before {
          position: absolute;
          content: "";
          width: 100%;
          height: 100%;
          left: 0;
          top: -5px;
          border-radius: 50%;
          border-bottom: 5px solid transparent;
        }

        .loader::after {
          border-top: 5px solid #0984e3;
          ;
          transform: rotate(120deg);
        }

        .loader::before {
          border-top: 5px solid #e056fd;
          ;
          transform: rotate(-120deg);
        }

        @keyframes animate {
          0% {
            transform: rotate(0deg);
          }

          100% {
            transform: rotate(360deg);
          }
        }

        .loader span {
          animation: animate .5s linear infinite reverse;
        }
      }

当监听到readyState===4时,隐藏加载动画,清空定时器

_this.timer = setInterval(() => {
      if ((_this.videourl ?? '') !== '') {
        _this.readyState = document.querySelector('video').readyState
        if (_this.readyState === 4) {
          clearInterval(_this.timer)
        }
      }
    }, 200);

下图为点击课程卡片进入课程播放界面,设置autoplay自动播放,默认播放第一个节点视频:

image.png

这张图是点击课程的某个节点进入,播放该节点视频

image.png

点击节点切换视频用 @node-click="handleNodeClick",在handleNodeClick中查询该节点信息,并设置让它高亮就行了。

当然你还得做好万一这个节点没有视频资源的准备,无视频资源时放张图 image.png

以上就是这个简单的课程播放界面