小程序视频播放列表的问题

942 阅读1分钟

需求是要做一个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>

最终效果如下:

参考文档:

csdn解决方案