需求是要做一个video的列表,类似票圈的首页,一开始的想法其实很简单,无非就是拿到数据后渲染出列表来,大概的代码就是
<block v-for="(item, index) of list" :key="index">
<view class="cu-item shadow custom-margin">
<view class="video-cont img-box">
<video
controls
object-fit="contain"
:show-mute-btn="true"
:enable-play-gesture="true"
:poster="item.img"
:src="item.video_url"
:id="`video${item.id}`"
@error="videoError"
/>
</view>
</view>
</block>
很简单,初步的效果出来了,视频也显示了出来,nice。
但是要知道多视频并不能同时播放噢,只能保留一个正在播放的视频。这个需求也很简单,分三步实现
- 获取到上一个播放视频的id
- 获取当前播放视频的id
- 暂停上一个播放的视频,播放当前的视频
这里就需要用到一个API—uni.createVideoContext,主要用来获取播放的实例,简单代码如下
handlePlay(e) { //监听video的play事件
let curId = e.currentTarget.id //存储当前需要播放的id
if (!this.playId) {//第一次播放
let videoCxt = uni.createVideoContext(curId, this)
videoCxt.play() //播放视频
this.playId = curId
this.playVideo = videoCxt
} else {//非第一次播放
if (this.playId !== curId && this.playVideo) {
this.playVideo.pause() //暂停上一个视频
}
let videoCxt = uni.createVideoContext(curId, this)
videoCxt.play() //播放当前视频
this.playId = curId
this.playVideo = videoCxt
}
}
其实到这一步基本上大功告成了,但是经过测试发现,ios下很多视频都加载不出来,查了很多资料发现:一个页面建议只出现一个video,官方的原话是:
不建议同个页面使用多个video组件,建议不超过3个video,如果要实现video列表功能,请进行优化
所以换了一种思路:
- video全部替换成image
- 点击image,获取到当前的id,通过v-if来动态替换video
- video设置成autoplay(重中之重)
Js
handlePlay(index, id) {
this.playId=id
}
html
<video
controls
object-fit="contain"
:show-mute-btn="true"
:enable-play-gesture="true"
:show-center-play-btn="false"
:src="item.video_url"
:autoplay="true"
:id="`video${item.id}`"
@error="videoError"
:data-index="index"
v-if="item.id===playId"/>
<view @click="handlePlay(index,item.id)" v-else>
<view class="img-mask"/>
<view class="img-box-play">
<image src="/static/images/play-01.png" mode="widthFix"/>
</view>
<image :src="item.img" mode="aspectFit"/>
</view>
最终效果如下:
参考文档: