vue3 视频播放功能整体复盘梳理

       

        回顾工作中对视频的处理,让工作中处理的问题的经验固化成成果,不仅仅是完成任务,还能解答任务的知识点。

遇到的问题

        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>

上一篇:线程(Linux)-三、多线程


下一篇:vitess sysbench性能测试