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()
    }
  }
},
  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
您好,这是两个不同的功能,我来分别回答。 1. Java实现微信、手机号登录 要实现微信、手机号登录,您需要先了解微信开放平台和短信验证码服务商的接口文档。 对于微信登录,您可以通过微信开放平台提供的OAuth2.0授权登录接口实现。具体步骤如下: - 用户点击登录按钮,跳转到微信授权页面。 - 用户在微信授权页面上确认授权登录。 - 微信授权服务器返回授权码。 - 通过授权码获取access_token和openid。 - 使用openid作为用户唯一标识,完成登录逻辑。 对于手机号登录,您可以使用短信验证码服务商提供的接口实现。具体步骤如下: - 用户输入手机号码并点击获取验证码按钮。 - 调用短信验证码服务商提供的发送短信验证码接口,将验证码发送到用户手机上。 - 用户输入收到的验证码并点击登录按钮。 - 调用短信验证码服务商提供的校验短信验证码接口进行验证。 - 验证通过后,使用手机号码作为用户唯一标识,完成登录逻辑。 2. 微信小程序获取手机号授权用户登录功能 要在微信小程序中获取用户手机号码,您可以通过微信小程序提供的button组件和wx.login接口实现。具体步骤如下: - 用户点击获取手机号按钮。 - 调用wx.login接口获取临时登录凭证code。 - 将code发送到您的后台服务器,调用微信提供的auth.code2Session接口换取openid和session_key。 - 后台服务器返回openid和session_key给前端。 - 前端调用微信提供的button组件,设置属性为open-type="getPhoneNumber",并将session_key作为参数传递。 - 用户点击授权登录按钮,微信返回加密的手机号信息和iv。 - 前端将加密的手机号信息和iv发送到后台服务器,调用微信提供的解密算法解密手机号信息。 - 后台服务器返回解密后的手机号给前端,完成登录逻辑。 希望以上回答能够帮助您。如果您还有疑问,请随时提出。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值