uniapp实现视频上下滑动功能(小程序)以及video组件的暂停和播放

uni推荐使用swiper组件实现,在video组件的下面介绍有写。
这里实现方式是:
父组件先用swiper组件实现纵向滑动,然后在每个swiper-item中插入视屏组件video-item-vx(自己定义的组件),在video-item-vx组件中实现视屏播放,具体别的细节根据需要自己实现。
注意:不能无限添加swiper-item,16个以上会容易出现视频异常的报错,可以10个swiper-item循环,替换数据即可。

第一步:维护10个swiper-item,10个以上替换数据即可。
第二步:判断上滑还是下滑up down,用来判断videoIndex加减。
第三步:维护一个下标 videoIndex , 作用就是取二维数组的数据进行渲染。
第四步:维护一个二维数组作为数据源 [ [10条数据], [...] , ...]。 初始的数据源可以请求两次,避免了好多麻烦。
第五步:判断是否要首尾衔接

一、视屏屏纵向上下滑动

1、父组件html

<!-- swiper组件 -->
<swiper
  class="swiper"
  :indicator-dots="indicatorDots"
  :autoplay="autoplay"
  :duration="duration"
  :vertical="vertical"
  :circular="circular"
  :current="current_"
  @animationfinish="videoAnimationfinish"
  @change="change"
  @transition="transition"
  style="height:100%"
>
  <template v-if="videoListAll[parseInt(videoIndex / 10)]">
    <swiper-item v-for="(item, index) in videoListAll[parseInt(videoIndex / 10)]" :key="item.videoId" 		  
	  @catchtouchmove="catchTouchMove" v-show="total -1 >= videoIndex >= 0">
      <video-item-vx
        :videoDetail="item"
        :current="current_"
        :videoIndex="index"
      ></video-item-vx>
    </swiper-item>
  </template>
</swiper>

备注:data中的数据
indicatorDots: false, // 是否显示面板指示点
autoplay: false, // 是否自动切换
vertical: true, // 滑动方向是否为纵向
duration: 800,
circular: false, // 是否衔接滑动
current_: 0, // 当前所在视频的 index
videoIndex: 0, // 维护的视屏下标
videoListAll:[], // 数据源
total: 0, // 视频总条数
isTwo: false, // 初始的时候是否请求了两次
isSuccess: true, // 请求是否失败
touchDirection: ‘’, // 滑动方向
current0: ‘’, // 上一个swiper下标
isRequest: false, // 是否在请求数据

2、父组件的js

@transition事件swiper-item 的位置发生改变时会触发,用来判断上滑还是下滑

transition (event) {
	// 在export default外定义一个数组 touchArr
	// <script>
	// let touchArr = []
	// export default {}
	// <script/>
   touchArr.push(event.detail.dy)
   if( touchArr.length > 1 ){
     if( touchArr[touchArr.length-1] - touchArr[touchArr.length-2] > 0){
       this.touchDirection = 'up'
     }else{
       this.touchDirection = 'down'
     }
   }
 },

@change事件swiper-item 的current下标改变时触发,用来维护videoIndex下标

change (event) {
   console.log('==========(触发了change)========>>>')
   touchArr = []
   // 维护下标
   // console.log('==========(touchDirection(change里面的))========>>>', this.touchDirection)
   if (this.touchDirection == 'down') {
     this.videoIndex--
   } else if (this.touchDirection == 'up') {
     this.videoIndex++
     this.circular = false // 每次videoIndex改变先设为false
   }
   // 防止维护的下标为负的时候白屏
   if (this.videoIndex < 0) {
     this.videoIndex = 0
     this.current_ = 0
   }
   // 防止维护的下标大于总数时候白屏
   if (this.videoIndex >= this.total) {
     this.videoIndex = this.total - 1
     this.current_ = this.total - 1
   } else {
     // 修正swiper下标
     this.current_ = this.videoIndex % 10
   }
 },

@animationfinish事件

	// swiper动画结束执行
    videoAnimationfinish(event) {
      // 如果在请求中,swiper不做首尾衔接
      if (this.isRequest) {
        this.circular = false // 不衔接
        uni.showToast({title: '加载中', icon: 'none', duration: 1000})
        return
      }
      // 没有数据了
      if (this.videoIndex == this.total-1) {
        uni.showToast({title: '没有更多了', icon: 'none', duration: 1000})
        return
      }
    },

监听维护的videoIndex下标,从而维护数组

watch: {
    videoIndex (val) {
      // 维护数组
      let videoIndex_ = this.videoIndex % 10
      let index_ = parseInt(this.videoIndex / 10)
      // 判断是否衔接
      this.isCircular(videoIndex_)
      // 加载数据
      if (this.touchDirection == 'up' && videoIndex_ == 4) { // 第5个加载数据
        if (!this.videoListAll[index_+1]) { // 如果有数据就不加载了
          this.videoList(index_)
        }
      }
      // 请求失败时第九个再次请求
      if (this.touchDirection == 'up' && videoIndex_ == 8) {
        if (!this.videoListAll[index_+1] && !this.isSuccess) { // 如果有数据就不加载了
          this.videoList(index_)
        }
      }
      // 分享参数
      let detail = this.videoListAll[index_][videoIndex_]
      if (detail) {
        this.videoIdFX = detail.videoId
        this.title = detail.title
        this.videoImageFile = detail.videoImageFile && detail.videoImageFile.imageUrl;
      }
      
      // 标记上一个下标
      this.current0 = this.videoIndex % 10

	  this.current_ = videoIndex_
    }
  },

判断是否衔接

isCircular (type) {
   // 1、维护的下标小于等于0时
   if (this.videoIndex <= 0) {
     this.circular = false
     return
   }
   // 2、维护的下标大于等于总数时
   if (this.videoIndex >= this.total-1) {
     this.circular = false
     return
   }
   // 3、总数小于等于10时
   if (this.total <= 10) {
     this.circular = false
     return
   }
   // 4、总数大于10
   if (type == 0) {
     this.circular = true
     console.log('==========(circular是否衔接1)========>>>', this.circular)
     return
   } else if (type == 9) {
       this.circular = true
       console.log('==========(circular是否衔接2)========>>>', this.circular)
       return
   } else {
       this.circular = false
   }
 }

请求数据源

// 页面初始化
async initPage() {
  if(this.videoIndex % 10 ===0 && Number(this.pageNum)>1){
     this.pageNum  = Number(this.pageNum) - 1
  }
  this.videoList();
},
// 获取视频列表
videoList(index) {
  if (this.isRequest) return // 防止重复请求
  this.isRequest = true
  this.isSuccess = false
  this.$fetch({
    url: 'VIDEO_LIST_VX',
    data: {
      themeId: this.themeId || '',
      pageNum: this.pageNum,
      queryType: this.queryType,
      channelType: 'MP',
      accountId: this.$store.state.accountId // || 'F00012306'
    }
  }).then((res) => {
    if (res.code === '000000' && res.data) {
      let videoListAll = res.data.list;
      console.log('=======发了请求videoListAll=====>>>', videoListAll)
      this.isloading = true
      if (videoListAll.length <= 0 && this.total >= 10) {
        this.$store.commit('setShowPageLoading', false);
        return
      }
      this.videoListAll[Number(this.pageNum)-1] = videoListAll
      // 处理视频顺序
      let that = this
      index = index || Number(this.pageNum)-1
      if (!this.isTwo && that.pageNum >= that.option.pageNum) {
        this.videoListAll[index].map((item, index) => {
          if (item.videoId == that.videoId) {
            that.current_ = index
            that.videoIndex = index + (Number(this.pageNum)-1) * 10 
            that.current0 = index
            that.title = item.title
            that.videoImageFile = item.videoImageFile && item.videoImageFile.imageUrl;
            that.videoId = ''
            this.$store.commit('setShowPageLoading', false);
          }
        })
        if (that.pageNum > that.option.pageNum) this.isTwo = true
      }
      console.log('==========(视频列表数据)========>>>',this.videoListAll)
      that.total = that.total + videoListAll.length
      this.pageNum  = Number(this.pageNum) + 1
      this.isSuccess = true
      this.isRequest = false
      if (!this.isTwo) {
        console.log('==========(请求第二次)========>>>')
        this.videoList()
      }
      this.isCircular(this.videoIndex % 10) // 请求成功再调一次衔接判断
    } else {
      this.isSuccess = false
      res.message && uni.showToast({title: res.message, icon: 'none'});
      this.isloading = true
      this.$store.commit('setShowPageLoading', false)
    }
  }).finally(() => {
    this.isRequest = false
    // this.$store.commit('setShowPageLoading', false);
  });
},
二、子组件实现视屏播放与暂停

使用uni的video组件实现,更多详情参照uni官网
先使用uni的createVideoContext()方法获取video对象,再使用video对象的play()和pause()方法实现播放和暂停
1、子组件的html

	<video
	  id="myVideo"
	></video>
	<!-- 自定义播放按钮 -->
	<div @click.stop="playVideo">
	  <img class="play-btn" src="@/static/images/video-button.png"/>
	</div>

2、子组件的js
在mounted或created中根据video组件的id获取video对象指向video

	// 监听传过来的参数判断视频的播放与暂停
	watch: {
	    current: {
	      immediate: true,
	      handler: function() {
	        this.video = uni.createVideoContext('myVideo', this);
	        this.$nextTick(() => {
	          if (this.current != this.videoIndex) {
	            this.stopPlay()
	          }else {
	            this.playVideo()
	          }
	        })
	      }
	  }
	  },
	mounted () {
		// 创建视频对象
		this.video = uni.createVideoContext('myVideo', this);
	},
	methods: {
		// 自定义播放按钮
		playVideo () {
			this.video.play() // 播放视频
			// this.video.pause() // 暂停视频
		}
	}
### 回答1: 可以使用uni-app提供的video组件实现上滑播放视频功能,具体代码如下: <template> <view class="container"> <video :src="videoUrl" @play="onPlay" @pause="onPause" @ended="onEnded"></video> </view> </template> <script> export default { data() { return { videoUrl: 'http://example.com/video.mp4', isPlaying: false } }, methods: { onPlay() { this.isPlaying = true }, onPause() { this.isPlaying = false }, onEnded() { this.isPlaying = false } } } </script> <style> .container { width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; } video { width: 100%; height: 100%; } </style> 在这个代码中,我们使用uni-app提供的video组件播放视频,通过监听play、pauseended事件来控制视频播放状态。同时,我们使用了isPlaying变量来记录视频是否正在播放。在模板中,我们将video组件放在一个容器中,并设置容器的宽高为100%,使得视频可以占满整个屏幕。在样式中,我们设置了video组件的宽高为100%,使得视频可以自适应屏幕大小。 ### 回答2: 实现uniapp小程序上滑播放视频可以通过以下步骤: 1. 在uniapp的页面上,引入uni-media组件,用于播放视频uni-media是uniapp封装的视频播放组件,可以将视频播放器放置在页面上。 2. 在页面上声明一个变量,用于控制视频是否播放。例如,可以定义一个变量叫做`isPlaying`,初始值为false。 3. 监听页面的滑动事件,可以使用`@scroll`或者`@touchmove`等事件,以在滑动时触发相关操作。 4. 在滑动事件中,判断用户的滑动方向滑动距离,可以通过事件的`direction``deltaY`属性获取。如果向上滑动且滑动距离足够长,就将`isPlaying`变量置为true,表示开始播放视频5. 在uni-media组件中添加条件判断,根据`isPlaying`变量的值来控制视频播放。如果`isPlaying`为true,则播放视频;如果`isPlaying`为false,则暂停视频。 6. 最后,需要在页面顶部或者其他位置添加一个视频播放器的占位元素,例如一个图片或者视频封面图,作为触发播放视频的入口。当用户滑动触发播放后,可以隐藏占位元素,显示实际的视频播放器。 简单示例代码如下: ```html <!-- 在页面上添加 uni-media 组件 --> <template> <view> <image class="video-placeholder" src="video_cover.jpg" v-if="!isPlaying" @click="startPlaying"></image> <uni-media class="video-player" :src="videoSrc" :autoplay="isPlaying"></uni-media> </view> </template> <script> export default { data() { return { isPlaying: false, // 控制视频播放状态 videoSrc: 'video.mp4' // 视频链接 } }, methods: { startPlaying() { this.isPlaying = true; // 开始播放视频 } }, // 监听滑动事件 onScroll(event) { // 判断滚动方向 if (event.direction === 'up' && event.deltaY > 100) { this.isPlaying = true; // 向上滑动播放视频 } } } </script> <style> .video-player { width: 100%; height: 300px; } .video-placeholder { width: 100%; height: 300px; } </style> ``` 以上代码实现了在uniapp小程序上滑播放视频功能。通过监听滑动事件,判断滑动距离方向,控制视频播放的逻辑。在页面上添加`uni-media`组件作为视频播放器,并根据`isPlaying`的值来控制视频播放暂停。同时,通过添加一个视频播放器的占位元素,在用户滑动触发播放后,隐藏占位元素,显示实际的视频播放器。 ### 回答3: 要使用代码实现uniapp小程序上滑播放视频功能,可以按照以下步骤操作: 1. 创建一个页面用于展示视频,可以在该页面的 template 中添加一个 video 组件用于播放视频。 2. 在页面的 script 部分,定义一个 data 属性,用于保存视频播放状态相关参数。可以包括视频是否可播放、当前播放视频索引、视频的列表等。 3. 在页面的 created 生命周期钩子函数中,可以通过请求接口获取视频列表数据,并将数据保存在 data 中。 4. 在页面的 onReachBottom 函数中,监听上滑事件。当触发上滑事件时,可以在 data 中更新当前播放视频索引,实现上滑播放下一个视频效果5. 在页面的 onReady 函数中,监听视频播放事件。当视频开始播放时,可以通过 data 更新视频播放状态,用于控制页面其他部分的交互。 6. 在页面的 template 中,利用 v-if 或 v-show 来控制视频的显示与隐藏,根据数据中的播放状态来判断是否显示视频。 7. 可以添加一些交互操作,比如点击视频切换播放/暂停状态,或者点击列表项切换播放视频等。 这是一个大致的思路,具体的细节实现可以根据具体需求来进行调整完善。希望对你有帮助!
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值