VUE Video视频(播放/列表)

1. 概述

1.1 说明

  PC项目中的经常会有视频播放功能,播放一些课程视频或者直播回放等;视频有时是单个视频有时是多个视频,多个视频时通过点击播放列表中的某一项进行播放对应视频信息。

 2. 代码

2.1 页面处理

  • 视频播放标签使用h5中的<video>,当需要播放的视频列表数量大于1时,显示视频列表(使用iview中的标签<Tag>);
  • 视频中使用muted属性(规定视频的音频输出应该被静音);   ----若需进入直接播放,需加上此属性,因为chrome目前将video和audio的autoplay自动播放功能禁用
<!-- 直播回放视频组件(视频列表时展示列表信息) -->
<template>
  <div class="video-item-wrapper">
    <video
      ref="refVideo"
      width="900"
      height="506"
      controls
      muted
      :src="videoSrc" />
     <div class="video-item-tag" v-if="videoItemList.length>1">
       <Tag
        v-for="item in videoItemList"
        :key="item.vid"
        :name="item.name"
        :checked="item.checked"
        :color="item.checked?'error':'default'"
        checkable
        type="border"
        style="cursor:pointer"
        @on-change="videoItemTagChang">
        {{item.name}}
      </Tag>
    </div>
  </div>
</template>

2.2 逻辑处理

  • 需要播放的视频列表从外部传值到组件内
  • 判断是否需要展示视频列表;如果展示了视频列表,则视频列表要与播放的视频进行对应;
  • 视频播放后,可进行列表顺序播放。如视频列表中有3个视频,点击第一个视频进行播放后,视频播放完成后进行第二个视频自动播放,依此类推,到列表中的最后一个视频时停止自动播放,第一个视频待播放
  • 视频播放功能中加入定时器   -----用来对谷歌不支持有声音的视频自动播放问题的解决
<script>
export default {
  name: 'VideoItem',
  props: {
    videoArray: {
      type: Array,
      default() {
        return []
      },
    },
  },
  data() {
    return {
      videoSrc: '',
      videoPlayNum: 0,
      videoItemList: [],
    }
  },
  mounted() {
    this.videoSrc = this.videoArray[this.videoPlayNum].mediaUrl
    this.initvideoItemList()
    this.videoEventListener()
  },
  methods: {
    /**
     * 视频标签集合初始化
     */
    initvideoItemList() {
      this.videoItemList = this.videoArray.map(item => {
        return {
          vid: item.vid,
          name: item.name,
          checked: false,
          mediaUrl: item.mediaUrl,
        }
      })
      if (this.videoItemList.length > 1) {
        this.videoItemList[0].checked = true
      }
    },
    /**
     * 视频标签处理
     */
    videoItemTagChang(checked, name) {
      let checkedName = ''
      for (let i = 0; i < this.videoItemList.length; i++) {
        if (this.videoItemList[i].checked) {
          checkedName = this.videoItemList[i].name
          break
        }
      }
      // 当前选中标签再次点击时不进行处理
      if (checkedName !== name) {
        this.videoItemList.forEach(item => {
          item.checked = false
        })
        if (name) {
          this.videoItemList.forEach(item => {
            if (item.name === name) {
              item.checked = checked
            }
          })
          for (let i = 0; i < this.videoItemList.length; i++) {
            if (this.videoItemList[i].checked) {
              this.videoPlayNum = i
              this.videoSrc = this.videoItemList[i].mediaUrl
              setTimeout(() => {
                this.$refs.refVideo.play()
              }, 150)
              break
            }
          }
        }
      }
    },
    /**
     * 视频监听(对视频插件进行监听是否播放结束,若结束则去判断是否无缝衔接播放下一视频还是回归初始化)
     */
    videoEventListener() {
      const _this = this
      _this.$refs.refVideo.addEventListener('ended', function () {
        if (_this.videoPlayNum === (_this.videoArray.length - 1)) {
          _this.videoSrc = _this.videoArray[0].mediaUrl
          _this.videoPlayNum = 0
          _this.setVideoTagSelected()
        } else {
          _this.videoPlayNum += 1
          _this.setVideoTagSelected()
          _this.videoSrc = _this.videoArray[_this.videoPlayNum].mediaUrl
          setTimeout(() => {
            _this.$refs.refVideo.play()
          }, 150)
        }
      })
    },
    /**
     * 视频列表状态选中设置
     */
    setVideoTagSelected() {
      this.videoItemList.forEach(item => {
        item.checked = false
      })
      for (let i = 0; i < this.videoItemList.length; i++) {
        if (i === this.videoPlayNum) {
          this.videoItemList[i].checked = true
          break
        }
      }
    },
  },
}
</script>

2.3 样式处理

<style lang="less" scoped>
.video-item-wrapper{
  display: flex;
  flex-direction: column;
  .video-item-tag{
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    >*{
      margin-top: 26px;
    }
  }
}
</style>

 

posted @ 2020-08-05 09:21  ajuan  阅读(4031)  评论(0编辑  收藏  举报