【vue】el-carousel实现视频自动播放与自动切换到下一个视频功能:

文章目录


一、原因:

由于后端无法实现将多条视频拼接为一条视频,所以更改为由前端实现页面视频自动播放功能和播放完后,自动切换到下一个视频功能

二、实现代码:
bash 复制代码
<template>
  <div class="preview-content" v-loading="loading">
    <el-tabs v-model="activeName" @tab-click="tabClick">
      <!-- 视频预览 -->
      <el-tab-pane v-if="DisplayList.includes('video')" name="video" :label="`视频预览【${videoList.length}】`">
        <div v-if="videoList.length > 0" class="preview-content-box">
          <el-carousel ref="videoCarousel" @change="autoPlayVideo" :autoplay="false" :loop="false" style="width:100%"
            height="540px" :initial-index="0" :key="(Date.parse(new Date()) / 1000)" arrow="always"
            indicator-position="none">
            <el-carousel-item v-for="(item, index) in videoList" :key="index">
              <h2>{{ index + 1 }}/{{ videoList.length }}</h2>
              <video autoplay :muted="false" controls preload :id="`video-${index}`" width=100% height="100%">
                <source :src="item" type="video/mp4" />
                <object type="application/x-shockwave-flash" data="myvideo.swf">
                  <param name="movie" value="myvideo.swf" />
                  <param name="flashvars" value="autostart=true&amp;file=myvideo.swf" />
                </object>
                当前浏览器不支持video直接播放,点击这里下载视频:<a :href="item">下载视频</a>
              </video>
            </el-carousel-item>
          </el-carousel>
        </div>
        <div v-else class="noData">无视频</div>
      </el-tab-pane>
    </el-tabs>
  </div>
</template>

<script>
export default {
  props: {
    DisplayList: {
      type: Array,
      default() {
        return ['img', 'video', 'imgBYWeight', 'imgBYCar', 'imgBYUpload']
      }
    },
  },
  data() {
    return {
      activeName: 'img',
      loading: false,
      
      videoList: [],//视频列表
      player: [],
    };
  },
  methods: {
    loadData(record, type) {
      const that = this;
      console.log('图片/视频预览:', record)
      that.activeName = (type && type != null && type != undefined && that.DisplayList.includes(type)) ? type : that.DisplayList.length > 0 ? that.DisplayList[0] : 'img'
      that.videoList = []             //视频列表
      if (!(typeof record == 'object') || Object.keys(record).length == 0) { return }
      that.loading = true

      // 视频列表
      if (that.DisplayList.includes('video')) {
        record.videoList && record.videoList.length > 0 ? that.videoList = [...that.pushArr(record.videoList)] : null;
        record.allVideoList && record.allVideoList.length > 0 ? that.videoList = [...that.videoList, ...that.pushArr(record.allVideoList)] : null;

        this.$nextTick(() => {
          that.videoList.length > 0 ? that.$refs.videoCarousel.setActiveItem(0) : null;
          that.player = []
          that.sleep(1000).then(() => { that.activeName == 'video' ? that.autoPlayVideo(0) : null; })
        })
      }
      
      that.loading = false;
    },
    // 数组遍历判断是否需要拼接地址
    pushArr(arr) {
      if (!Array.isArray(arr) || arr.length == 0) { return [] }
      let newArr = []
      for (let index = 0; index < arr.length; index++) {
        const item = arr[index];
        if ((typeof item == 'object') && item.url) {
          item.url.includes("http") || item.url.includes(";base64,") ? newArr.push(item.url) : newArr.push(process.env.VUE_APP_FILE_URL + item.url)
        } else {
          item.includes("http") || item.includes(";base64,") ? newArr.push(item) : newArr.push(process.env.VUE_APP_FILE_URL + item)
        }
      }
      return newArr
    },
    tabClick(tab, event) {
      const that = this;
      if (tab.name == 'video') {
        that.videoList.length > 0 ? that.$refs.videoCarousel.setActiveItem(0) : null;
        that.player = []
        that.autoPlayVideo(0)
      }
    },
    //设置播放点,续播
    autoPlayVideo(index, oldVal) {
      const that = this;
      let currVideo = document.getElementById(`video-${index}`);
      if (currVideo == null) { return }
      if (that.player.includes(currVideo)) {
        that.player[index].currentTime = 0, that.player[index].muted = false, that.player[index].autoplay = true, that.player[index].play().catch((err) => { });
        that.player[oldVal].currentTime = 0, that.player[oldVal].muted = true, that.player[oldVal].autoplay = false, that.player[oldVal].pause();
      } else {
        currVideo.currentTime = 0;//设置播放点
        currVideo.muted = false;//设置非静音
        that.sleep(100).then(() => {
          currVideo.play().catch((err) => { })
          that.player.includes(currVideo) ? null : that.player.push(currVideo);
          that.player.forEach((item, i) => { if (i != index) { item.autoplay = false, item.pause() } })
          that.player[index].addEventListener('ended', function (e) { //结束
            console.log("播放结束", e.target.id, that.player)
            that.$refs.videoCarousel.next()
          }, false);
        })
      }
    },
  },
  beforeDestroy() {
    this.videoList = []             //视频列表
    this.player = []
  },
}
</script>
三、遇到的问题:
【1】问题:el-carousel页面的视频不更新

文章链接:【vue】element强制刷新el-carousel的dom:

【2】问题:多按几次左按钮,其中跳过没有播放的视频没有销毁,造成再次自动播放时会跳页

将video存放到player里面,并修改video的播放状态

相关推荐
m0_7482382733 分钟前
项目升级Sass版本或升级Element Plus版本遇到的问题
前端·rust·sass
G佳伟1 小时前
【亲测有效】百度Ueditor富文本编辑器添加插入视频、视频不显示、和插入视频后二次编辑视频标签不显示,显示成img标签,二次保存视频被替换问题,解决方案
chrome·百度·音视频
升讯威在线客服系统1 小时前
如何通过 Docker 在没有域名的情况下快速上线客服系统
java·运维·前端·python·docker·容器·.net
AsBefore麦小兜1 小时前
Vite vs Webpack
前端·webpack
LaughingZhu1 小时前
PH热榜 | 2025-02-23
前端·人工智能·经验分享·搜索引擎·产品运营
道不尽世间的沧桑3 小时前
第17篇:网络请求与Axios集成
开发语言·前端·javascript
diemeng11194 小时前
AI前端开发技能变革时代:效率与创新的新范式
前端·人工智能
bin91536 小时前
DeepSeek 助力 Vue 开发:打造丝滑的复制到剪贴板(Copy to Clipboard)
前端·javascript·vue.js·ecmascript·deepseek
晴空万里藏片云8 小时前
elment Table多级表头固定列后,合计行错位显示问题解决
前端·javascript·vue.js
曦月合一8 小时前
html中iframe标签 隐藏滚动条
前端·html·iframe