12_微信小程序之微信视频号滚动自动播放视频效果实现

一.获取视频的分辨率、时长、缩略图

微信小程序提供了三种方式可以获取视频的分辨率、时长:

  • wx.getVideoInfo(Object) :只能用于本地视频

  • VideoDecoder.start(Object) :可用于网络视频或者本地视频

  • 借助video标签的bindloadedmetadata回调: 可用于网络视频或者本地视频,但必须在video标签被渲染的情况下才能获取到,并且获取速度较慢

      /*** @author gale* 传入视频链接,获取视频分辨率,时长,缩略图(视频第一帧的数据)*/decoderSource: function (source) {return new Promise((resolve, reject) => {var decoder = wx.createVideoDecoder()decoder.on("start", (res) => {//获取视频分辨率var width = res.widthvar height = res.height//获取视频时长var duration = res.duration/1000var formatDur = this.formatDuration(duration)//获取视频的缩略图,即第一帧的图像var frameData = decoder.getFrameData()while (!frameData) {frameData = decoder.getFrameData()}var fileName = source.substring(source.lastIndexOf("/") + 1, source.lastIndexOf("."))let pngData = upng.encode([new Uint8ClampedArray(frameData.data).buffer], frameData.width, frameData.height)let base64 = wx.arrayBufferToBase64(pngData)var filePath = wx.env.USER_DATA_PATH + "/" + fileName + ".png"var systemManager = wx.getFileSystemManager()systemManager.writeFileSync(filePath, base64, "base64")resolve({width: width,height: height,duration: duration,formatDur: formatDur,thumbnail: filePath,src: source})decoder.remove()})decoder.start({source: source,mode: 1})})}
    

二.微信小程序中,同一个页面存在多个播放器的坑

在微信小程序中,一个页面内,存在多个播放器时,会导致部分视频不能正常播放,同一页面存在多个video时,video无法正常播放一直在加载转圈

三.格式化视频时长

  /*** @author gale* 格式化视频时长,如 14.6 格式化成 00:14*/formatDuration: function(seconds) {var format = ""var h = parseInt(seconds/3600),m = parseInt(seconds%3600/60),s = parseInt(seconds%3600%60);if(h>0){h = h<10 ? '0'+h : hformat += h+":"}m = m<10 ? '0'+m : m s = s<10 ? '0'+s : s format+=m+":"+sreturn format;}

四.在列表中先渲染视频的缩略图和时长,播放当前视频时,将图片替换为video

这里采用自定义组件的方式实现

<!--components/video-list/index.wxml-->
<scroll-view class="video-list" scroll-y bindscroll="onScroll"><view class="list"><view class="video-item-wrapper" style="width: {{item.videoWidth}}px;" wx:for="{{_videoList}}"><view class="video-item" style="height: {{item.videoHeight}}px; background: #00f;"><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="{{item.thumbnail}}"/><view class="action"><view class="play-wrapper" bindtap="play" data-index="{{index}}"><image class="play" src="./images/play.png"/><view style="margin-top: 10rpx;">{{item.formatDur}}</view></view></view></block></view></view></view>
</scroll-view>
// components/video-list/index.js
Component({/*** 组件的属性列表*/properties: {videoList: {type: Array,value: [],observer: function(newVal, oldVal) {var that = thisconst query = that.createSelectorQuery()query.select(".video-list").boundingClientRect()query.exec((res) => {var itemWidth = res[0].widthfor(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 = thisthis.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 = thisvar index = event.currentTarget.dataset.indexthis.setData({playIndex: index})}}
})
/* components/video-list/index.wxss */
.video-list {width: 100%;height: 100%;
}.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;
}

这里给播放器上下各100rpx的间距,是因为让整个item高度撑开,以保证每一个视频都能滑动自动播放,实际上传视频的时候,只需要让上传的视频宽高比能撑开播放器而不设置间距即可

五.实现滑动自动播放

// components/video-list/index.js
Component({/*** 组件的属性列表*/properties: {videoList: {type: Array,value: [],observer: function(newVal, oldVal) {var that = thisconst query = that.createSelectorQuery()query.select(".video-list").boundingClientRect()query.exec((res) => {var itemWidth = res[0].widthfor(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})const query = that.createSelectorQuery()query.selectAll(".video-item-wrapper").boundingClientRect()query.exec((res) => {var items = res[0]const query = that.createSelectorQuery()query.select(".list").boundingClientRect()query.exec((res) => {var listHeight = res[0].heightthat.setData({videoItems: items,listHeight: listHeight})})})})}},playIndex: {type: Number,value: -1,observer: function(newVal, oldVal) {var that = thisthis.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: [],videoItems: [],listHeight: 0,contentHeight: 0},lifetimes: {attached: function() {var systemInfo = wx.getSystemInfoSync()var contentHeight = systemInfo.windowHeightthis.setData({contentHeight: contentHeight})}},/*** 组件的方法列表*/methods: {play: function(event) {var that = thisvar index = event.currentTarget.dataset.indexthis.setData({playIndex: index})},onScroll: function(event) {var contentHeight = this.data.contentHeightvar scrollHeight = event.detail.scrollHeightvar scrollTop = event.detail.scrollTopvar scrollPosition = Math.floor(scrollTop + contentHeight/2)var index = this.getCurrentPlayIndex(scrollPosition, scrollHeight)var playIndex = this.data.playIndexif(index != playIndex) {this.setData({playIndex: index})}},getCurrentPlayIndex: function(scrollPosition, scrollHeight) {var contentHeight = this.data.contentHeightvar listHeight = this.data.listHeight ? this.data.listHeight:0var top = scrollHeight - listHeightvar current = -1var videoItems = this.data.videoItemsif(!videoItems || videoItems.length <= 0) {return -1} var offset = top - videoItems[0].topfor(var i=0; i<videoItems.length; i++) {if(scrollPosition >= (videoItems[i].top + offset) && scrollPosition <= (videoItems[i].bottom + offset)) {current = ibreak}}return current},}
})

12_微信小程序之微信视频号滚动自动播放视频效果实现相关推荐

  1. 微信小程序 --- CSS实现仿网易云音乐播放界面效果(黑胶唱片与唱针纯CSS实现)

    下面代码的效果是网易云音乐唱针和黑胶唱片的CSS效果实现方式,播放等并没贴出来 实现效果的范围 动态图效果预览: stylusW,panW是获取系统宽度计算后的参数 wxml部分: <!-- 黑 ...

  2. 微信小程序web-view 外部引用h5页面调用摄像头录制视频 配有提示音

    微信小程序web-view 外部引用h5页面调用摄像头录制视频 配有提示音 1.目前的需求是什么 2.都踩了那些坑 1.小程序 2.h5语音提示 3.语音合成声音录制不进去,ios有时候是麦克风,有时 ...

  3. 全新动态视频壁纸微信小程序源码下载支持多种分类短视频另外也有静态壁纸

    这是一款主打动态视频壁纸的一款微信小程序源码 当然啦,里面也是有静态壁纸的 其实这款小程序也可以说是短视频小程序都可以 该款小程序全采集, 大家应该知道小编之前也发过一款动态壁纸的小程序 不过那款是没 ...

  4. 新动态视频壁纸微信小程序源码_支持多种分类短视频-也有静态壁纸

    这是一款主打动态视频壁纸的一款微信小程序源码,当然啦,里面也是有静态壁纸的. 其实这款小程序也可以说是短视频小程序都可以,该款小程序全采集,另外支持多种流量主!! 下载链接: 新动态视频壁纸微信小程序 ...

  5. 微信小程序与公众号区别PHP,微信小程序和微信公众号的区别是什么?

    微信小程序和微信公众号的区别是什么? 2019-08-17 09:10 微信公众号和小程序都是基于微信平台来使用的,而微信自带的十几亿流量也是导流到小程序和公众号上的.越来越多的商家都在运营微信小程序 ...

  6. 微信小程序打开微信公众号中的文章实战教程

    微信小程序获取微信公众号文章实战 情景 微信小程序中有一块功能是需要从关联的微信公众平台中获取最新的一篇文章进行展示,看了微信公众号的官方文档与微信小程序的文档,好像都没有找到类似的接口,所以想了一个 ...

  7. 微信小程序(微信应用号)开发ide安装解决方法

    微信小程序(微信应用号)开发ide安装解决方法 参考文章: (1)微信小程序(微信应用号)开发ide安装解决方法 (2)https://www.cnblogs.com/muyixiaoguang/p/ ...

  8. 微信小程序使用微信公众号的模板消息进行消息推送开发流程

    微信小程序使用微信公众号的模板消息进行消息推送开发流程 微信公众号服务号,微信公众号订阅号,微信公众号开发者平台,微信小程序 这些的账号都是独立的不能共用 微信开放平台开发者资质认证审核费用为300元 ...

  9. 50行代码实现的艺术签名设计微信小程序,轻松对接公众号,涨粉神器,学习赚钱两不误.微信公众号引流工具.html,python学习小项目.艺术签名设计微信小程序,前端学习小项目有趣的项目

    50行代码实现的艺术签名设计微信小程序,轻松对接公众号,涨粉神器,学习赚钱两不误 先看效果 这个小程序实现艺术签名设计的功能 对接到公众号之后,相当于给你的公众号添加了一个功能,别人关注公众号后,可以 ...

最新文章

  1. [Django](1093, quot;You can#39;t specify target table #39;fee_details_invoices#39; for update in...
  2. Pandas把dataframe的索引、复合索引变换为数据列:包含单索引到单列(重命名)、复合索引到多数据列、复合索引的其中一个水平变换为数据列、
  3. ubuntu 上code blocks 建glut工程时问题
  4. python游戏-练习项目19:使用python制作游戏(上)
  5. php 环境变量有什么用,什么是环境变量,Linux环境变量及作用
  6. Springboot整合Nacos配置中心
  7. Calendar类和GregorianCalendar类
  8. matlab已知斜率画直线,MATLAB 霍夫变换 连接斜率相同的直线
  9. 三大微分中值定理及泰勒中值定理证明
  10. DeleteRow()
  11. 减速机的漏油原因及快速维修方法
  12. 7_22_html_美食网设计
  13. APISpace 星座查询API
  14. 10.11 学习记录
  15. “终端有鸿蒙,云端有安超!” 鸿蒙落地,安超有什么新动作?
  16. win11 ms-settings;display(该文件没有与之关联的应用来执行该操
  17. 牛宝宝取名起名字:寓意前程似锦、仪表不凡的男孩名字
  18. shell脚本练习2023年下岗版
  19. python3 word转pdf
  20. 当支付有了“智慧” 未来我们将体验到什么样的智慧城市?

热门文章

  1. RSA no_padding加密(modulus、exponent构造公钥)
  2. 微信跳一跳辅助之JAVA版(最容易理解的算法)实现原理分析
  3. 【瑞芯微Rockchip Linux平台】SoftAp需求实现(3)动态获取BT Mac地址并更新beacon帧中的mac信息
  4. 【OS】Linux环境下配置固定IP地址--静态IP地址(不能上外网问题)
  5. svg实现多个元素拖拽
  6. 阿里云 ACP 认证,分享下经验心得
  7. app inventor+tinywebDB远程控制掌控板
  8. 微信小程序页面添加背景图,图片全屏显示
  9. 2018年创翼 开wifi方法 适合电脑小白
  10. [cstc2021]wp