IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 18_微信小程序之微信视频号滚动自动播放视频效果实现2.0 -> 正文阅读

[移动开发]18_微信小程序之微信视频号滚动自动播放视频效果实现2.0

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()
    }
  }
},
  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-06-29 19:12:58  更:2022-06-29 19:14:52 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年3日历 -2024/3/28 21:30:09-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码