持续创作,加速成长!这是我参与「掘金日新计划 · 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 - 可用数据足以开始播放
在视频没有加载完成之前,需要有一个炫酷的加载中动画
代码如下:
<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自动播放,默认播放第一个节点视频:
这张图是点击课程的某个节点进入,播放该节点视频
点击节点切换视频用 @node-click="handleNodeClick",在handleNodeClick中查询该节点信息,并设置让它高亮就行了。
当然你还得做好万一这个节点没有视频资源的准备,无视频资源时放张图
以上就是这个简单的课程播放界面