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>