当前位置:网站首页>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()
}
}
},
边栏推荐
- 关于QByteArray存储十六进制 与十六进制互转
- 百度智能云牵头打造智能云综合标准化平台
- AEM: Nanlin fan Ben et al. - plant rhizosphere growth promoting bacteria control soybean blight
- 飞凌搭载TI AM62x的ARM核心板/开发板首发上市,亮相Embedded World 2022
- [Luogu p4320] road meets (round square tree)
- 【小程序项目开发-- 京东商城】uni-app之自定义搜索组件(中)-- 搜索建议
- Baidu AI Cloud takes the lead in building a comprehensive and standardized platform for smart cloud
- 研发一款国产ARM智能边缘计算网关需要什么
- University of Oslo: Li Meng | deep reinforcement learning based on swing transformer
- 1.11 - 总线
猜你喜欢

AttributeError: ‘tuple‘ object has no attribute ‘layer‘问题解决

Teach you JDBC hand in hand -- structure separation

1.11 - 总线

antv x6节点拖拽到画布上后的回调事件(踩大坑记录)

Arduino开发之按键检测与正弦信号输出

Key detection and sinusoidal signal output developed by Arduino

Test shift right: Elk practice of online quality monitoring

图解网络:什么是虚拟路由器冗余协议 VRRP?

Hdu3507 (slope DP entry)

Unity learns from spaceshooter to record the difference between fixedupdate and update in unity for the second time
随机推荐
Illustrated network: what is virtual router redundancy protocol VRRP?
Vulkan-实践第一弹
【AutoSAR 七 工具链简介】
Linux Software: how to install redis service
瑞萨电子RZ/G2L开发板上手评测
百度智能云牵头打造智能云综合标准化平台
Rk3568 development board evaluation (II): development environment construction
【AutoSAR 十 IO架构】
Advanced pointer (I)
【AutoSAR 十二 模式管理】
这不平凡的两年,感谢我们一直在一起!
Kubernetes resource object introduction and common commands (V) - (NFS & PV & PVC)
[AUTOSAR I overview]
【AutoSAR 九 C/S原理架构】
How SQLSEVER removes data with duplicate IDS
基于ARM RK3568的红外热成像体温检测系统
Solve the cache problem of reactnative using WebView
[case sharing] let the development of education in the new era advance with "number"
全志A40i/T3如何通过SPI转CAN
Detailed explanation of pod life cycle