小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
本文已参与 「掘力星计划」 ,赢取创作大礼包,挑战创作激励金。
🎯前言
视频播放可能在日常的业务场景中并不多,但绝对不陌生,选择好用的插件往往事半功倍。今天笔者将带来一个场景介绍一下由字节跳动开源的西瓜播放器(点它),功能很多很强大😎。
本文使用Vue+Xgplayer
测试视频url:sf1-cdn-tos.huoshanstatic.com/obj/media-fe/xgplayer_doc_video/mp4/xgplayer-demo-360p.mp4
videoList数据可以灵活处理, 简而言之只需要一个视频的url和一个图片的url。
🎯预期效果
西瓜视频有这样一个预览的效果(很多视频网站都有),我们今天的内容就是这个效果
🎯最终效果
🎯xgplayer简单使用
🫀安装xgplayer
npm install xgplayer
复制代码
在需要的vue组件中引入并初始化
import Player from 'xgplayer'
let player = new Player({
id:'' , //标签的id名或者 使用 el:dom元素
url: 视频url,
videoInit: true,
poster: 封面图,
controls: false,
playbackRate: [0.5, 0.75, 1, 1.5, 2],
whitelist: [
''
],
fluid: false,
// download: true,
width: '100%',
height: '200px'
})
复制代码
这样就能创建一个可以在指定的容器里创建一个视频播放器了。
🎯实现思路
在上文的完整效果里这个案例显然是循环出来的多个容器,这里就要考虑Player实例的问题了,创建一个还是多个,这里有两种思路,本文采用第一种。顺便一提,真实业务中数据来源于接口服务(坑在这)。
1.循环创建多个容器,并为每个创建实例,滚动加载会带来实例过多的问题;为了避免,可以采用分页的形式。
2.循环创建容器,不创建实例,只展示封面,移入容器时销毁前一个实例,创建当前实例(比较优解),读者可以尝试一下。
根据效果,不难看出,移入容器的时候视频播放,移出的时候当前视频暂停,这样保持同时只有一个在播放。 我这里准备了一个img封面层和一个video视频层,默认显示图片层,使用两个事件mouseEnter和mouseleave动态的控制对应容器的显示和隐藏(也有个小坑),并对对应索引的实例操作(暂停,销毁等)。
startPlay(data,index){
this.$refs['img'+index][0].style.display="none"
this.$refs['video'+index][0].style.display="block"
this.$nextTick(()=>{
this.dom[index].play()
})
},
move(data,index){
this.$refs['img'+index][0].style.display="block"
setTimeout(() => {
this.dom[index].pause()
}, 0);
this.$refs['video'+index][0].style.display="none"
},
复制代码
🎯完整代码
复制代码
<template>
<div class="video">
<div class="video-content" id="videoScroll" ref="videoScrollBar">
<div class="card" v-for="(item,index) in videoList" :key="index" >
<div style="width:100%;height:200px"
@mouseenter="startPlay(item,index)"
@mouseleave="move(item,index)">
<div
:ref="`img${index}`"
style="width:100%;height:200px;background-size: cover;"
:style="{'background-image':`url(${item.spsltlj+'/'+item.spslt}) `}">
</div>
<div style="display:none;overflow:hidden" :ref="`video${index}`">
</div>
</div>
<div class="title">
{{item.spmc}}
</div>
</div>
</div>
</div>
</template>
<script>
import Player from 'xgplayer'
import { loadVideoList } from "@/api/video"
export default {
name: 'Video',
components: {
TitleField: Title
},
data () {
return {
// 视频的url由 splj+spbh组成,缩略图poster由spsltlj+spslt组成
videoList:[
{
splj:'',
spbh:'',
spsltlj:'',
spslt:''
}
],
dom:[],
}
},
created() {
this.setBaseList()
},
mounted() {
},
methods: {
async setBaseList(){
const res =await loadVideoList(this.form)
this.videoList=res.data.records
setTimeout(() => {
if(this.videoList.length){
this.videoList.forEach((item,index)=>{
this.init(item,index)
},1000)
}else{
this.dom.length=0
}
})
},
init (data,index) {
this.dom[index]= new Player({
el: this.$refs['video'+index][0],
url: data.splj+'/'+data.spbh,
videoInit: true,
poster:data.spsltlj+'/'+data.spslt, //封面图
// cssFullscreen: true,
lang: 'zh-cn',
controls: false,
playbackRate: [0.5, 0.75, 1, 1.5, 2],
whitelist: [
''
],
ignores: ['play'],
fluid: false,
// download: true,
width: '100%',
height: '200px'
})
},
startPlay(data,index){
this.$refs['img'+index][0].style.display="none"
this.$refs['video'+index][0].style.display="block"
this.$nextTick(()=>{
this.dom[index].play()
})
},
move(data,index){
this.$refs['img'+index][0].style.display="block"
setTimeout(() => {
this.dom[index].pause()
}, 0);
this.$refs['video'+index][0].style.display="none"
},
}
}
</script>
<style scoped lang = "less">
.card{
width: 18%;
margin: 0 20px 20px 0;
float: left;
}
.title{
width: 100%;
color: #000;
height:40px;
line-height: 40px;
background-color: #ffffff;
font-weight: 600;
padding-left: 10px;
}
</style>
复制代码
🎯两个小坑
🫀 数据还没加载完就初始化实例的问题
这边使用定时器延时执行,如果直接循环,西瓜播放器播放时会报错,大体上就是实例没初始化完成。同理,播放的事件中也要等dom加载完成后调用play方法播放。
async setBaseList(){
const res =await loadVideoList(this.form)
this.videoList=res.data.records
setTimeout(() => {
if(this.videoList.length){
this.videoList.forEach((item,index)=>{
this.init(item,index) //初始化视频实例
},1000)
}else{
this.dom.length=0
}
})
},
复制代码
🫀 mouseenter和mouseleave
使用v-for循环的时候,mouseenter和mouseleave要加在父元素身上。
<div class="card" v-for="(item,index) in videoList" :key="index" >
<div style="width:100%;height:200px"
@mouseenter="startPlay(item,index)"
@mouseleave="move(item,index)">
<div
:ref="`img${index}`"
style="width:100%;height:200px;background-size: cover;"
:style="{'background-image':`url(${item.spsltlj+'/'+item.spslt}) `}">
</div>
<div style="display:none;overflow:hidden" :ref="`video${index}`">
</div>
</div>
<div class="title">
{{item.spmc}}
</div>
</div>
复制代码
🎯总结
以上是西瓜视频一个简单的demo使用介绍,更多强大的功能可以去官网体验,比如弹幕,画中画一些简单的配置。除此之外,这款开源插件不仅可以播放视频,还可以进行直播,不止可以用在PC端,也可以用在移动端。