回顾工作中对视频的处理,让工作中处理的问题的经验固化成成果,不仅仅是完成任务,还能解答任务的知识点。
遇到的问题
1、如何隐藏下载按钮?
video 标签中的controlslist属性是可以用来控制播放器上空间的显示,在原来默认的基础上进行优化,多个值可选择的值:
nodownload: 不要下载、
nofullscreen: 不要全屏、
noremoteplayback: 不要远程回放。
2、控制视频起始位置?
video标签中有currentTime属性,这个可以设置视频从什么时间节点开始播放,默认是0秒。
3、当视频运行到指定时间点暂停一次,第二次不暂停?
在视频播放时,会同步更新timeupdate方法,可以同步记录当前的播放数据。
4、如何在视频更新时,记录播放的状态?
每次调用组件,可以直接运用initData方法,传参,设置视频的数据;其中@play方法,是在开启播放时执行;@pause在视频暂停时播放。@seeked 是在拉动视频播放条的回调。
5、如何路由判断是图片、文件、还是视频,切换不同的标签?
在下文的末尾有判断路由的状态封装方法:vue3 常用的一些字符串处理-CSDN博客
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 = truevideoVisible.value.src = item.urlvideoVisible.value.title = item.titlevideoVisible.value.chaptersId = chaptersIdif (copyType.value == 1) {videoVisible.value.link = '复制的路由地址'} else {videoVisible.value.link = '复制的路由地址'}//视频播放暂停节点videoVisible.value.endTime = item.endTimelearnedTime.value = item.studySecondstakeInfo.value = {detailId: courseId,chaptersId: chaptersId,catalogueId: item.id,}
}
//关闭弹框时,回调父级方法,子级与父级之间通讯
const closeVideo = () => {videoVisible.value.visible = falseemits('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 = trueisPlay.value = falsee.target.pause()}}
}
//定时器,开始播放是,打开定时器
const initData = (type, courseId, chaptersId, item) => {//每次播放时,将原来的定时器进行清理if (renew.value) {clearInterval(renew.value)renew.value = null}copyType.value = typeshowVideo(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 = truerenew.value = setInterval(() => {handleRenew()}, 5000);
}//点击暂停视频,记录当前播放情况
const onPause = () => {isPlay.value = falseclearInterval(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>