微信小程序实现类似抖音效果

背景
公司有个小程序项目要求做类似抖音的效果。
由于微信小程序受video兼容性的原因,总会产生很多意想不到的关于video的兼容性bug。
为了解决视频列表太多造成的卡顿,判断页面中只有滑动到当前页面的才是视频。其他为预览图。

下面是主要实现代码,涉及到的列表数据需要自己准备,只提供逻辑代码。
wxml:

<view class="root">

  <view class="video {{touch==true? 'transfrom' : '' }}" style="transform:translateY(-{{current*100}}%);" bindtouchstart='touchstart' bindtouchmove='touchmove'  bindtouchend='touchend' bindtouchcancel='touchcancel'>
    <view wx:for="{{videoList}}" class='videoitem' wx:key="{{item}}">
      <video src="{{item.video[0].v_url}}" wx:if="{{current==index}}" object-fit="cover" bindtap='multipleTap'  loop='{{true}}'
        autoplay='{{true}}' custom-cache="{{true}}" controls='{{false}}' show-progress="{{true}}" show-fullscreen-btn="{{false}}" show-play-btn="{{false}}" show-center-play-btn="{{false}}" enable-progress-gesture="{{false}}" vslide-gesture-in-fullscreen="{{false}}"
        poster="{{item.video[0].pre_url}}" show-center-play-btn="{{false}}" show-play-btn="{{false}}">
      </video>
      <image src="{{item.video[0].pre_url}}" class="preImage" mode='aspectFit'  lazy-load="{{true}}" wx:else></image>
    </view>
  </view>
</view>

wxss:

page{
  height: 100%;
}
.root{
  overflow: hidden;
  height: 100%;
  position: relative;
}
.video{
  width: 100%;
  height: 100%;
  display: block;
  position: absolute;
  top:0;
  left: 0;
}
.transfrom{
  transition: transform  0.4s ease-out;
}
.videoitem{
  height: 100%;
  background:#000000;
}

js


Page({
  /**
   * 页面的初始数据
   */
  data: {
    videoDetail: '',
    start: 0,
    current:0,
    startTouch:'',
    videoList: [], //接口返回的视频列表。
    touch: false,
    touchStartTime: 0, //触摸开始时间
    touchEndTime: 0, // 触摸结束时间
    lastTapTime: 0, // 单击事件点击后要触发的函数
    lastTapTimeoutFunc: null

  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    this.getVideoList()

  },
  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady: function (options) {
    this.isShowGuide()
  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow: function () {
    
  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide: function () {

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload: function () {

  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh: function () {
    
  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom: function () {
    
  },
  getVideoList: function (value) {
    let d = this.data
    let param = {
      "tag_id": d.curTagid,
      "start": d.start,
      "page_size": 10,
      "customer_id": 0
    }
    app.httpPost('/xxx/xxx/video/video_list', param, {
      success: (res) => {
        if (res.data.status === 0) {
          let videoList = d.videoList.concat(this.picksItem(res.data.result, this.data.needItem))
          this.setData({
            videoList:videoList,
            current:value
          })
        } else {
          console.log(res.data.err_msg)
        }
      },
      fail: (e) => {
        console.log('请求失败')
      }
    })
  },
  
  // 下面主要模仿滑动事件
  touchstart: function (e) {
    this.setData({
      touchStartTime: e.timeStamp,
      showGuide:false
    })
    let startTouch = e.changedTouches[0]
    this.setData({
      startTouch: startTouch,
      touch: false
    })
  },

  touchmove: function (e) {
    let Y = e.changedTouches[0].pageY - this.data.startTouch.pageY;
  },

  touchend: function (e) {
    this.setData({
      touchEndTime : e.timeStamp
    })
    this.getDirect(this.data.startTouch, e.changedTouches[0])
  },

  touchcancel: function (e) {
    this.getDirect(this.data.startTouch, e.changedTouches[0])
  },
  // 计算滑动方向
  getDirect: function (start, end) {
    var X = end.pageX - start.pageX,
      Y = end.pageY - start.pageY;
    if (Math.abs(X) > Math.abs(Y) && X > 0) {
      console.log("left 2 right");
    }
    else if (Math.abs(X) > Math.abs(Y) && X < 0) {
      console.log("right 2 left");
    }
    else if (Math.abs(Y) > Math.abs(X) && Y > 40) {
      if(this.data.current>0){
        this.setData({
          touch: true,
          transitionOver: false
        })
        this.pre()
      }else{
        this.setData({
          current:0
        })
      }
    }
    else if (Math.abs(Y) > Math.abs(X) && Y < -40) {
      if(this.data.current < this.data.videoList.length-1){
        this.setData({
          touch: true
        })
        this.next()
      }else{
        this.getVideoList(this.data.videoList.length)
        this.setData({
          current: this.data.videoList.length -1
        })
      }
    }
  },
  changeVideo: function (value) {
    let d = this.data
    if(value < 0 || d.videoList.length <= value) {
      return 
    }
    let last = d.videoList.length - d.current
    if(this.data.videoList.length%10===0){
      this.setData({
        start: d.videoList.length
      })
      last < 2 && this.getVideoList(value) 
    }else{
      this.setData({
        start: d.videoList.length-1
      })
    }
  },
  // 播放上一个
  pre: function () {
    this.setData({
      current: this.data.current-1,
    })
    this.changeVideo(this.data.current)
  },

  // 播放下一个
  next: function () {
    this.setData({
      current: this.data.current+1,
    })
    this.changeVideo(this.data.current)
  }
})

 

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值