背景
公司有个小程序项目要求做类似抖音的效果。
由于微信小程序受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)
}
})