当前位置:网站首页>18_微信小程序之微信视频号滚动自动播放视频效果实现2.0
18_微信小程序之微信视频号滚动自动播放视频效果实现2.0
2022-07-03 00:26:00 【andr_gale】
18_微信小程序之微信视频号滚动自动播放视频效果实现2.0
一.先上效果图

关于这个效果呢,我之前已经实现过一个12_微信小程序之微信视频号滚动自动播放视频效果实现,只不过之前的实现是监听scroll-view的onscroll,根据scroll-view的滑动位置动态计算出播放的index来控制自动播放,本文将采用微信小程序为我们提供的IntersectionObserver来实现。
二.IntersectionObserver
IntersectionObserver wx.createIntersectionObserver(Object component, Object options)
- 在页面中使用: IntersectionObserver wx.createIntersectionObserver(this, {observeAll: true}),observeAll为true可同时监听多个节点
- 在自定义组件中使用:IntersectionObserver this.createIntersectionObserver({observeAll: true})
IntersectionObserver IntersectionObserver.relativeTo(string selector, Object margins)
- 使用选择器指定一个节点,作为参照区域
IntersectionObserver.observe(string targetSelector, IntersectionObserver.observeCallback callback)
- 指定目标节点的选择器并监听由relativeTo指定的参照区域与目标节点是否相交,由于我们需要监听多个video节点,所以这里的目标节点选择器我们使用class选择器即可。
- 当目标节点与参照区域相交时,callback(res)返回的res中的intersectionRatio大于0
- 当目标节点与参照区域不相交时,callback(res)返回的res中的intersectionRatio等于0
IntersectionObserver.disconnect()
最后当页面或组件销毁的时候,需调用IntersectionObserver.disconnect()取消监听
在页面中使用时,在onUnload方法中调用即可
在组件中使用时,在detached方法中调用即可
三.视频列表渲染
细节的地方可参考12_微信小程序之微信视频号滚动自动播放视频效果实现,这里就直接上代码了。
<scroll-view class="video-list" scroll-y>
<view class="list">
<view class="video-item-wrapper video" style="width: {
{
item.videoWidth}}px;" wx:for="{
{_videoList}}">
<view class="video-item" style="height: {
{
item.videoHeight}}px;">
<video wx:if="{
{playIndex == index}}" id="player" class="player" src="{
{item.src}}" object-fit="contain" show-center-play-btn="{
{false}}" custom-cache="{
{true}}" autoplay="{
{true}}"></video>
<block wx:else>
<image class="thumbnail" src="{
{
'data:image/jpg;base64,' + item.thumbnail}}"/>
<view class="action">
<view class="play-wrapper" bindtap="play" data-index="{
{index}}">
<image class="play" src="./images/ic_play.png"/>
<view style="margin-top: 10rpx;">{
{item.formatDur}}</view>
</view>
</view>
</block>
</view>
</view>
<view style="width: 100%; height: {
{
_videoList[0] ? _videoList[0].videoHeight + 'px' : '600rpx'}};"></view>
</view>
</scroll-view>
.video-list {
width: 100%;
height: 100vh;
}
.list {
width: 100%;
}
.video-item-wrapper {
background: #000;
/* padding-top: 200rpx; padding-bottom: 200rpx; */
margin-top: 20rpx;
}
.video-item-wrapper:last-child {
margin-bottom: 20rpx;
}
.video-item {
position: relative;
width: 100%;
}
.thumbnail, .player {
position: absolute;
left: 50%;
top: 50%;
width: 100%;
height: 100%;
transform: translate(-50%, -50%);
}
.action {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, .6);
}
.play-wrapper {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: #fff;
}
.play {
width: 48rpx;
height: 48rpx;
}
Component({
/** * 组件的属性列表 */
properties: {
videoList: {
type: Array,
value: [],
observer: function(newVal, oldVal) {
var that = this
const query = that.createSelectorQuery()
query.select(".video-list").boundingClientRect()
query.exec((res) => {
var itemWidth = res[0].width
for(var i=0; i<newVal.length; i++) {
newVal[i].videoWidth = Math.floor(itemWidth)
newVal[i].videoHeight = Math.floor(itemWidth/(newVal[i].width/newVal[i].height))
}
that.setData({
_videoList: newVal
})
})
}
},
playIndex: {
type: Number,
value: -1,
observer: function(newVal, oldVal) {
var that = this
this.setData({
playIndex: newVal
})
if(newVal >= 0) {
var videoContext = wx.createVideoContext('player', that)
if(videoContext) {
videoContext.stop()
}
var timer = setTimeout(function() {
clearTimeout(timer)
var videoContext = wx.createVideoContext('player', that)
if(videoContext) {
videoContext.play()
}
}, 500)
}
}
}
},
/** * 组件的初始数据 */
data: {
_videoList: []
},
/** * 组件的方法列表 */
methods: {
play: function(event) {
var that = this
var index = event.currentTarget.dataset.index
this.setData({
playIndex: index
})
}
}
})

四.参照节点选定
这里我们以第一个视频的高度一半的位置作为参照节点即可,在实际应用的时候也可以根据自己的需求去设置参照节点。
<scroll-view class="video-list" scroll-y>
<view class="list">
<view class="video-item-wrapper video" style="width: {
{
item.videoWidth}}px;" wx:for="{
{_videoList}}">
<view class="video-item" style="height: {
{
item.videoHeight}}px;">
<video wx:if="{
{playIndex == index}}" id="player" class="player" src="{
{item.src}}" object-fit="contain" show-center-play-btn="{
{false}}" custom-cache="{
{true}}" autoplay="{
{true}}"></video>
<block wx:else>
<image class="thumbnail" src="{
{
'data:image/jpg;base64,' + item.thumbnail}}"/>
<view class="action">
<view class="play-wrapper" bindtap="play" data-index="{
{index}}">
<image class="play" src="./images/ic_play.png"/>
<view style="margin-top: 10rpx;">{
{item.formatDur}}</view>
</view>
</view>
</block>
</view>
</view>
<view style="width: 100%; height: {
{
_videoList[0] ? _videoList[0].videoHeight + 'px' : '600rpx'}};"></view>
</view>
</scroll-view>
<view class="relativeView" style="top: {
{
_videoList[0] ? _videoList[0].videoHeight/2 + 'px':'30%'}};"></view>
.relativeView {
position: fixed;
left: 0;
top: 30%;
width: 100%;
height: 1px;
background: #f00;
}

我们根据上面的图片分析一波,默认情况下,第一个视频与参照物相交,控制第一个视频播放即可,当向上滑动到第二个视频与参照物相交时,控制第二个视频播放即可
五.滑动自动播放
上面已经分析清楚了,直接上代码。
<scroll-view class="video-list" scroll-y>
<view class="list">
<!-- 指定data-index="{
{index}}",当监听到有video节点与参照节点相交时,可以通过index获取到当前时第几个视频标签与参照节点相交 -->
<view class="video-item-wrapper video" style="width: {
{
item.videoWidth}}px;" wx:for="{
{_videoList}}" data-index="{
{index}}">
<view class="video-item" style="height: {
{
item.videoHeight}}px;">
<video wx:if="{
{playIndex == index}}" id="player" class="player" src="{
{item.src}}" object-fit="contain" show-center-play-btn="{
{false}}" custom-cache="{
{true}}" autoplay="{
{true}}"></video>
<block wx:else>
<image class="thumbnail" src="{
{
'data:image/jpg;base64,' + item.thumbnail}}"/>
<view class="action">
<view class="play-wrapper" bindtap="play" data-index="{
{index}}">
<image class="play" src="./images/ic_play.png"/>
<view style="margin-top: 10rpx;">{
{item.formatDur}}</view>
</view>
</view>
</block>
</view>
</view>
<view style="width: 100%; height: {
{
_videoList[0] ? _videoList[0].videoHeight + 'px' : '600rpx'}};"></view>
</view>
</scroll-view>
<view class="relativeView" style="top: {
{
_videoList[0] ? _videoList[0].videoHeight/2 + 'px':'30%'}};"></view>
Component({
/** * 组件的属性列表 */
properties: {
videoList: {
type: Array,
value: [],
observer: function(newVal, oldVal) {
var that = this
const query = that.createSelectorQuery()
query.select(".video-list").boundingClientRect()
query.exec((res) => {
var itemWidth = res[0].width
for(var i=0; i<newVal.length; i++) {
newVal[i].videoWidth = Math.floor(itemWidth)
newVal[i].videoHeight = Math.floor(itemWidth/(newVal[i].width/newVal[i].height))
}
that.setData({
_videoList: newVal
})
this.intersectionObserver = this.createIntersectionObserver({
observeAll: true})
this.intersectionObserver.relativeTo('.relativeView')
.observe(".video", (res) => {
let index = res.dataset.index
let intersectionRatio = res.intersectionRatio
if(intersectionRatio > 0) {
that.setData({
playIndex: index
})
}
})
})
}
},
...
},
...
})

大功告成…
六.隐藏参照节点
注意:这里不能给参照节点设置 hidden=“{ {true}}” 或者使用wx:if,否则,将监听不到目标节点与参照节点相交的情况,而应该使用z-index。
<view class="relativeView" style="top: {
{
_videoList[0] ? _videoList[0].videoHeight/2 + 'px':'30%'}}; z-index: -9999"></view>
最后在组件销毁的时候,取消监听即可
lifetimes: {
detached: function() {
if (this.intersectionObserver) {
this.intersectionObserver.disconnect()
}
}
},
边栏推荐
- Attributeerror: 'tuple' object has no attribute 'layer' problem solving
- Test shift right: Elk practice of online quality monitoring
- 【C语言】分支和循环语句(上)
- lex && yacc && bison && flex 配置的问题
- [AUTOSAR + IO Architecture]
- Shell 实现文件基本操作(切割、排序、去重)
- Key detection and sinusoidal signal output developed by Arduino
- 【JetCache】JetCache的配置说明和注解属性说明
- Leetcode-849: maximum distance to the nearest person
- 1.11 - bus
猜你喜欢

Detailed explanation of pod life cycle
![[AUTOSAR I overview]](/img/e4/b97c6beebf6f431d2d7cf209c6683e.png)
[AUTOSAR I overview]

In the first half of 2022, there are 10 worth seeing, and each sentence can bring you strength!

Rk3568 development board evaluation (II): development environment construction

Reading and writing speed of Reza rz/g2l arm development board storage and network measurement

The arm core board / development board of Feiling equipped with Ti am62x made its debut in embedded world 2022
![[love crash] neglected details of gibaro](/img/d6/baa4b5185ddaf88f3df71a94a87ee2.jpg)
[love crash] neglected details of gibaro

【AutoSAR 九 C/S原理架构】

Callback event after the antv X6 node is dragged onto the canvas (stepping on a big hole record)

1.12 - Instructions
随机推荐
There is an unknown problem in inserting data into the database
【日常训练】871. 最低加油次数
【AutoSAR 四 BSW概述】
[introduction to AUTOSAR seven tool chain]
Rust ownership (very important)
kubernetes资源对象介绍及常用命令(五)-(NFS&PV&PVC)
【AutoSAR 六 描述文件】
leetcode-241:为运算表达式设计优先级
1.12 - 指令
【小程序项目开发-- 京东商城】uni-app之自定义搜索组件(中)-- 搜索建议
Shell 实现文件基本操作(sed-编辑、awk-匹配)
深度剖析数据在内存中的存储
tail -f 、tail -F、tailf的区别
Shell implements basic file operations (cutting, sorting, and de duplication)
Rk3568 development board evaluation (II): development environment construction
Leetcode-241: designing priorities for operational expressions
【AutoSAR 十二 模式管理】
How SQLSEVER removes data with duplicate IDS
Array common operation methods sorting (including ES6) and detailed use
Is there a free text to speech tool to help recommend?