最近公司的小程序需要在关注页面加一个滚动页面自动播放视频功能,研究出来之后,在此写个博客记录一下。
自己是技术小白,写的不好bug多,请轻喷!!!!
这篇博客只是给自己记录一下。有更好的方法也欢迎讨论 ~ ~
实现思路
- 在页面初加载时,拿到所有视频的top值,且如果第一条帖子是视频的话就播放。因为小程序没有DOM结构,所以要借助wx.createSelectorQuery();来拿到top值,具体代码后面会贴出。
- 因为视频有横屏和竖屏拍摄,高度不一,所以需要拿到横屏与竖屏的宽度值以便之后做判断,我这里的视频宽高是从后端返回的数据
- 计算出横屏视频上下滑动开始播放区域和竖屏视频上下滑动开始播放区域
- 利用滚动监听onPagescroll(),当上 \ 下滑到视频播放区域时视频播放,目前还没做视频播放暂停,后期测试阶段会再进一步优化。
- 下面贴出代码
在要获取高度的视频上加个id,因为视频未播放时一般是放个视频截图在那占位,所以要获取图片的高度,并且要获取到scroll-view的高度,以便之后计算差值。
<!-- 视频设为自动播放,当 selectPlayid 与 item.id 相等时播放,视频截图隐藏,截图由后端生成 -->
<block wx:if="{{selectPlayid==item.id}}">
<video class="vedioitem vediotext" catchtap="vedioClick" bindended='clocechuang' data-item='{{item}}' id="vedio{{item.id}}" src="{{item.vedio}}" style="width:{{item.vedio_widths}}px;height:{{item.vedio_heights}}px" controls autoplay></video>
</block>
<scroll-view scroll-y id='guanzhuscrollid' class='tiezitext' bindscroll="scrolls" style="width:100%;white-space: nowrap;padding-top:106px">
<image class='tzplayerimg' id='tiezibody{{item.id}}' src='{{item.avatar}}'></image>
初加载时执行函数getimgTop()
// getviewHeight: function (id) {
// var query = wx.createSelectorQuery();
// //选择id
// query.select('#tiezibody' + id).boundingClientRect()
// query.exec(function (res) {
// //res就是 所有标签为mjltest的元素的信息 的数组
// // console.log(res);
// //取高度(213px)
// // console.log(res[0].height);
// })
// },
getimgTop: function () {
var that = this;
// 创建节点选择器
var query = wx.createSelectorQuery();
var viewIndex = this.data.viewIndex;
var viewId = this.data.articles[viewIndex].id;
let articles = this.data.articles;
var arr = [], brr = []
// 拿到所有视频的id值
for (let i = 0; i < articles.length; i++) {
arr.push(articles[i].id)
}
this.setData({
imgidlist: arr
})
// 拿到所有视频的DOM值
for (let i = 0; i < arr.length; i++) {
// 选择id
query.select('#tiezibody' + arr[i]).boundingClientRect()
query.exec(function (res) {
// res里有宽高top等字段
brr = res
})
}
// 判断第一个帖子是否是视频,是视频就播放
query.select('#tiezibody' + viewId).boundingClientRect()
query.exec(function (res) {
that.setData({
toplist: res,
selectPlayid: articles[0].id
})
that.gettopList();
})
// 拿到scroll-view的高度
query.select('#guanzhuscrollid').boundingClientRect()
query.exec(function (res) {
let len = res.length - 1;
that.setData({
scrollHeight: parseInt(res[len].height)
})
})
// console.log(articles);
},
计算横 \ 竖视频上下滑动时播放视频的区域
gettopList: function () {
// 所有dom值
var toplist = this.data.toplist;
// 所有的帖子数据,包含视频宽高
var articles = this.data.articles;
var brr = [];
var arr = [];
var crr = [];
// 拿到所有视频的top值
for (let i = 0; i < toplist.length; i++) {
brr.push(toplist[i].top);
}
var imgidlist = this.data.imgidlist;
// 将视频的top值、id、width、下滑开始播放区域高度start end、上滑开始播放区域高度start_1 end_1 存入数组arr
for (let j = 0; j < imgidlist.length; j++) {
if (this.data.articles[j].vedio != '' && this.data.articles[j].vedio) {
arr[j] = {};
arr[j].top = brr[j];
arr[j].id = imgidlist[j];
arr[j].width = articles[j].vedio_widths;
// 横屏
if(arr[j].width > 300){
arr[j].start = parseInt(arr[j].top - 585);
arr[j].end = parseInt(arr[j].top -195);
arr[j].start_1 = parseInt(arr[j].top + 28);
arr[j].end_1 = parseInt(arr[j].top - 385);
}else{ // 竖屏
arr[j].start = parseInt(arr[j].top - 490);
arr[j].end = parseInt(arr[j].top + 10 );
arr[j].start_1 = parseInt(arr[j].top + 140);
arr[j].end_1 = parseInt(arr[j].top - 208);
}
}
}
// 过滤掉没有视频的帖子
for (let v = 0; v < arr.length; v++) {
if (arr[v] != '' && arr[v]) {
crr.push(arr[v]);
}
}
console.log(crr)
this.setData({
tops: crr,
})
},
滚动监听 ———— 因为里面有多个判断和循环,所以我在这做了节流
// 滚动监听 + 节流
onPageScroll: toolUtil.throttle(function(e) {
var tops = this.data.tops;
// console.log(e[0].scrollTop);
var _this = this;
//当滚动的top值最大或最小时,为什么要做这一步是因为在手机实测小程序的时候会发生滚动条回弹,所以为了处理回弹,设置默认最大最小值
if (e[0].scrollTop <= 0) {
e[0].scrollTop = 0;
} else if (e[0].scrollTop > this.data.scrollHeight) {
e[0].scrollTop = this.data.scrollHeight;
}
//判断浏览器滚动条上下滚动
if (e[0].scrollTop > this.data.scrollTop || e[0].scrollTop == this.data.scrollHeight) {
//向下滚动
for (let i = 0; i < tops.length; i++) {
if (e[0].scrollTop >= tops[i].start && e[0].scrollTop <= tops[i].end){
this.setData({
selectPlayid: tops[i].id
})
// console.log('向下滚动tops['+i+']',tops[i].top);
}
}
} else {
//向上滚动
for (let i = 0; i < tops.length; i++) {
if (e[0].scrollTop <= tops[i].start_1 && e[0].scrollTop >= tops[i].end_1){
this.setData({
selectPlayid: tops[i].id
})
// console.log('向上滚动tops[' + i + ']', tops[i].start_1);
}
}
}
//给scrollTop重新赋值
setTimeout(function () {
_this.setData({
scrollTop: e[0].scrollTop
})
}, 0)
}),
节流函数我封装在了公用js中
/*函数节流*/
exports.throttle = function (fn, interval) {
var enterTime = 0;//触发的时间
var gapTime = interval || 300;//间隔时间,如果interval不传,则默认300ms
return function () {
var context = this;
var backTime = new Date();//第一次函数return即触发的时间
if (backTime - enterTime > gapTime) {
fn.call(context, arguments);
enterTime = backTime;//赋值给第一次触发的时间,这样就保存了第二次触发的时间
}
};
}
关于小程序节流和防抖有一个大佬的博客写的很清楚,大家对这方面有疑问的可以看看
补充!!!!
scroll-view里面不能包含video组件的!!这是个大坑,如果使用scroll-view在苹果机上退出全屏会重新回到顶部