回顾工作中对视频的处理,让工作中处理的问题的经验固化成成果,不仅仅是完成任务,还能解答任务的知识点。
遇到的问题
1、如何隐藏下载按钮?
video 标签中的controlslist属性是可以用来控制播放器上空间的显示,在原来默认的基础上进行优化,多个值可选择的值:
nodownload: 不要下载、
nofullscreen: 不要全屏、
noremoteplayback: 不要远程回放。
2、控制视频起始位置?
video标签中有currentTime属性,这个可以设置视频从什么时间节点开始播放,默认是0秒。
3、当视频运行到指定时间点暂停一次,第二次不暂停?
在视频播放时,会同步更新timeupdate方法,可以同步记录当前的播放数据。
4、如何在视频更新时,记录播放的状态?
每次调用组件,可以直接运用initData方法,传参,设置视频的数据;其中@play方法,是在开启播放时执行;@pause在视频暂停时播放。@seeked 是在拉动视频播放条的回调。
5、如何路由判断是图片、文件、还是视频,切换不同的标签?
在下文的末尾有判断路由的状态封装方法:vue3 常用的一些字符串处理-****博客
6、如何从操作上如何防止视频被下载?
两种方法可以同时进行,首先隐藏视频上的下载标签,即controlslist="nodownload";另外一种是防止右键下载,在video标签上嵌套一个div,并阻止右键点击事件,如 @contextmenu.prevent="menuPlayer()"。
除此之外还有一些其它的方法,如防盗链,将视频转换成数据流的形式,只是这些需求服务端的支持。
代码实施
<template>
<a-modal v-model:visible="videoVisible.visible" width="50%" title="课程预览" :footer="null" destroyOnClose
@cancel="closeVideo">
<div class="videoBox">
<div class="videoTitleBox">
<div class="videoTitle">{{ videoVisible.title }}</div>
<div class="videoCopy" @click="copyLink()">复制链接</div>
</div>
<div class="videoStyle" @contextmenu.prevent="menuPlayer()">
<video :src="videoVisible.src" controls controlslist="nodownload" :currentTime="learnedTime"
style="width:100%;height:100%;" disablePictureInPicture preload @timeupdate="timeupdate" @play="onPlay"
@pause="onPause" @seeked="seeked"></video>
</div>
</div>
</a-modal>
</template>
<script setup>
import { defineExpose, onBeforeUnmount, ref } from 'vue';
import defHttp from "@/utils/http.js";
import useClipboard from 'vue-clipboard3'
import { message } from 'ant-design-vue';
const props = defineProps(['info'])
const { toClipboard } = useClipboard()
const emits = defineEmits(['callback'])
const videoVisible = ref({ visible: false, src: "", title: "", chaptersId: "",isFirst:false,endTime:0 })
const currentTime = ref(0)
const learnedTime = ref(0)
const schedule = ref(0)
const isPlay = ref(false)
const renew = ref(0)
const copyType = ref(0)
const showVideo = (courseId, chaptersId, item) => {
videoVisible.value.visible = true
videoVisible.value.src = item.url
videoVisible.value.title = item.title
videoVisible.value.chaptersId = chaptersId
if (copyType.value == 1) {
videoVisible.value.link = '复制的路由地址'
} else {
videoVisible.value.link = '复制的路由地址'
}
//视频播放暂停节点
videoVisible.value.endTime = item.endTime
learnedTime.value = item.studySeconds
takeInfo.value = {
detailId: courseId,
chaptersId: chaptersId,
catalogueId: item.id,
}
}
//关闭弹框时,回调父级方法,子级与父级之间通讯
const closeVideo = () => {
videoVisible.value.visible = false
emits('callback')
}
//复制功能,将路由地址复制下来
const copyLink = async () => {
try {
// 复制
await toClipboard(videoVisible.value.link)
// 复制成功
message.success('复制成功');
} catch (e) {
// 复制失败
}
}
//视频播放时同步更新当前播放进度
const timeupdate = (e) => {
currentTime.value = e.target.currentTime
//当视频第一次播放到指定位置时,视频暂停;再开启时,视频不会暂停
if(!videoVisible.value.isFirst){
if(currentTime.value > videoVisible.value.endTime){
videoVisible.value.isFirst = true
isPlay.value = false
e.target.pause()
}
}
}
//定时器,开始播放是,打开定时器
const initData = (type, courseId, chaptersId, item) => {
//每次播放时,将原来的定时器进行清理
if (renew.value) {
clearInterval(renew.value)
renew.value = null
}
copyType.value = type
showVideo(courseId, chaptersId, item)
}
const takeInfo = ref({
detailId: '',
chaptersId: '',
catalogueId: '',
})
//记录视频播放情况
const handleRenew = () => {
if (currentTime.value > 0) {
let params = {
lessonsId: takeInfo.value.catalogueId,
seconds: parseInt(currentTime.value)
}
defHttp.post('更新学习进度接口', params).then(data => {
if (!data.Success) {
message.error(`${data.Message}`)
}
})
}
}
//播放视频时,开启定时器 记录视频播放情况,5秒每次
const onPlay = () => {
isPlay.value = true
renew.value = setInterval(() => {
handleRenew()
}, 5000);
}
//点击暂停视频,记录当前播放情况
const onPause = () => {
isPlay.value = false
clearInterval(renew.value);
handleRenew()
}
//拉取进度条事件,重新记录当前播放情况
const seeked = () => {
if (currentTime.value != 0) {
handleRenew()
}
}
//空方法,主要是阻止点击视频右键弹框时
const menuPlayer = () => {
}
//暴露初始方法,让组件在每次更新时,重新设置参数
defineExpose({
initData
})
</script>
<style lang="less" scoped>
.videoBox {
cursor: pointer;
.videoTitleBox {
display: flex;
justify-content: space-between;
align-items: center;
.videoTitle {
font-size: 14px;
color: rgba(102, 102, 102, 0.8);
}
.videoCopy {
border: 1px solid #D03E2C;
padding: 4px 10px;
border-radius: 4px;
}
}
.videoStyle {
margin-top: 10px;
}
}
</style>