实用于微信小程序(H5的话改一改也能用)的视频滑动切换组件
以前用过小程序提供的video-swiper组件, 其中的问题和bug也不做过多形容了。
为了我的项目进度,过后也没过多思考,没用应用video-swiper,而是用swiper和swiper-item简略实现了性能,起初本人测进去了个问题,然而客户没有反馈,测试也没有提bug,所以这个问题就耽误,当初抽空从新写个demo,等当前遇到相似的我的项目,再拿进去批改。
新写的这个demo就是参考了以前用过的轮播图组件的思维做的一个视频滑动切换组件,如果有其余问题,请大家不要悭吝,指导进去,谢谢!
还是间接上代码!!!
//index.tsconst randomColor: string[] = ['a', 'b', 'c', 'd', 'e', 'f', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9']interface BaseEvent extends WechatMiniprogram.BaseEvent { touches: Array<WechatMiniprogram.TouchDetail>}Page({ /** * 页面的初始数据 */ data: { distance: 0, list: <Array<string>>[], windowInfo: <WechatMiniprogram.WindowInfo>{}, }, loadMoreColor() { if (this.loading) return this.loading = true //视频汇合 let list = [ '' ] // for (let i = 0; i < 10; i++) { // let color = '#' // for (let n = 0; n < 6; n++) { // color += randomColor[Math.floor(Math.random() * randomColor.length)] // } // console.log(color); // list.push(color) // } setTimeout(() => { this.setData({ list: [...this.data.list, ...list] }, () => { this.currentIndex === 0 && this.createVideoContext() this.loading = false }) }, 2000); }, createVideoContext() { this.videoExample && this.videoExample.stop && this.videoExample.stop() this.videoExample = wx.createVideoContext(`video_${this.currentIndex}`) this.videoExample.play() }, videoExample: <Record<string, any> | null>null, //video实例 loading: false, //数据加载 currentIndex: 0, //以后swiper startLocation: <number>0, //手指摁下地位 endLocation: 0, //手指抬起地位 isTouchmove: false, //是否有滑动操作 inertiaRollState: true, //惯性滚动成果是否完结 true完结 false未完结 //触摸开始 touchstart(e: BaseEvent) { if (!this.inertiaRollState) return //记录滑动初始地位 this.startLocation = e.touches[0].clientY }, //触摸挪动 touchmove(e: BaseEvent) { //如果swiper以后地位是0且是下拉的动作 if ((this.currentIndex <= 0 && e.touches[0].clientY - this.startLocation > 0) || !this.inertiaRollState) return; console.log('touchmove'); this.isTouchmove = true this.endLocation = e.touches[0].clientY //e.touches[0].clientY - this.startLocation手指滑动的间隔 //this.currentIndex * this.data.windowInfo.screenHeight曾经卷下来的间隔 //distance一共卷下来的间隔 let distance = e.touches[0].clientY - this.startLocation - (this.currentIndex * this.data.windowInfo.screenHeight) this.setData({ distance: this.currentIndex < this.data.list.length - 1 ? distance : Math.abs(distance) > this.currentIndex * this.data.windowInfo.screenHeight + 50 ? -(this.currentIndex * this.data.windowInfo.screenHeight + 50) : distance }) }, //触摸完结 touchend() { //moveDistance手指滑动间隔 大于0(moveState为true)时是下拉, 小于0(moveState为false)时是上拉 let moveDistance = this.endLocation - this.startLocation let moveState = moveDistance > 0 this.endLocation = 0 this.startLocation = 0 //如果swiper以后地位是0且是下拉的动作 if ((this.currentIndex <= 0 && moveState) || !this.isTouchmove) return; this.isTouchmove = false this.inertiaRollState = false //手指滑动的间隔不小于1/4, swiper执行切换 if (Math.abs(moveDistance) >= this.data.windowInfo.screenHeight / 4) { let currentIndex = moveState ? this.currentIndex - 1 : this.currentIndex + 1 if (currentIndex < this.data.list.length) { //如果加载到最初一个视频, 去拉取新的列表 currentIndex === this.data.list.length - 1 && this.loadMoreColor() this.currentIndex = currentIndex this.inertiaRoll(moveState, -(this.currentIndex * this.data.windowInfo.screenHeight), true) return } } this.inertiaRoll(moveState, -(this.currentIndex * this.data.windowInfo.screenHeight)) }, touchcancel() { }, /** * moveState滑动状态 为true时是下拉, 为false时是上拉 * distance滑动间隔的起点地位 */ inertiaRoll(moveState: boolean, distance: number, swiper = false) { let baseNum = Math.abs(this.data.distance - distance) / 10 let intervalId = setInterval(() => { //下拉 值越来越大(从负无穷越来越靠近于0) 上拉 值越来越小(负无穷) let _d = moveState ? this.data.distance + baseNum : this.data.distance - baseNum if ((moveState && _d >= distance) || (!moveState && _d <= distance)) { //滑动切换实现 this.setData({ distance }, () => { swiper && this.createVideoContext() this.inertiaRollState = true }) clearInterval(intervalId) } else { this.setData({ distance: _d }) } }, 10) }, /** * 生命周期函数--监听页面加载 */ onLoad() { this.setData({ windowInfo: wx.getWindowInfo() }) this.loadMoreColor(); }})
<!--index.wxml--><view class="container" style="height: {{windowInfo.screenHeight}}px;"> <view class="list-view" catchtouchstart="touchstart" catchtouchmove="touchmove" catchtouchend="touchend" catchtouchcancel="touchcancel" style="margin-top: {{distance}}px;"> <view wx:for="{{list}}" wx:key="index" style="height: {{windowInfo.screenHeight}}px; background-color: {{item}};" class="list-item"> <video id="{{'video_' + index}}" src="{{item}}" loop style="width: 100%; height: 100%;"></video> </view> <view style="height: 50px; line-height: 50px; text-align: center;">加载中...</view> </view></view>
/**index.wxss**/.container { width: 100%; overflow: hidden; .list-view { .list-item { width: 100%; height: 100%; display: flex; align-items: center; } }}