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>