当前位置:网站首页>12_ Implementation of rolling automatic video playback effect of wechat video number of wechat applet
12_ Implementation of rolling automatic video playback effect of wechat video number of wechat applet
2022-07-03 01:03:00 【andr_ gale】
12_ The wechat video number of wechat applet scrolls and automatically plays the video effect
One . Get the resolution of the video 、 Duration 、 thumbnail
Wechat applet provides three ways to obtain the resolution of video 、 Duration :
wx.getVideoInfo(Object)
: Only for local videoVideoDecoder.start(Object)
: It can be used for network video or local videoWith the help of video Labeled bindloadedmetadata Callback : It can be used for network video or local video , But it must be in video Only when the label is rendered can we get , And the acquisition speed is slow
/** * @author gale * Incoming video link , Get video resolution , Duration , thumbnail ( Data of the first frame of the video ) */ decoderSource: function (source) { return new Promise((resolve, reject) => { var decoder = wx.createVideoDecoder() decoder.on("start", (res) => { // Get video resolution var width = res.width var height = res.height // How long to get the video var duration = res.duration/1000 var formatDur = this.formatDuration(duration) // Get a thumbnail of the video , That is, the image of the first frame 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 }) }) }
Two . Wechat applet , There are multiple players on the same page
In the wechat applet , In one page , When there are multiple players , Some videos will not play normally , There are multiple on the same page video when ,video It can't play normally. It's loading and rotating
3、 ... and . Format video duration
/** * @author gale * Format video duration , Such as 14.6 Format as 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 : h
format += h+":"
}
m = m<10 ? '0'+m : m
s = s<10 ? '0'+s : s
format+=m+":"+s
return format;
}
Four . First render the thumbnail and duration of the video in the list , When playing the current video , Replace the picture with video
Here, it is implemented in the way of custom components
<!--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({
/** * A list of properties of a 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)
}
}
}
},
/** * The initial data of the component */
data: {
_videoList: []
},
/** * A list of methods for a component */
methods: {
play: function(event) {
var that = this
var index = event.currentTarget.dataset.index
this.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;
}
Here is the player up and down 100rpx The distance between , Because let the whole item Height spread , To ensure that every video can slide and play automatically , When actually uploading videos , Just let the aspect ratio of the uploaded video support the player without setting the spacing
5、 ... and . Realize sliding automatic playback
// components/video-list/index.js
Component({
/** * A list of properties of a 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
})
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].height
that.setData({
videoItems: items,
listHeight: listHeight
})
})
})
})
}
},
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)
}
}
}
},
/** * The initial data of the component */
data: {
_videoList: [],
videoItems: [],
listHeight: 0,
contentHeight: 0
},
lifetimes: {
attached: function() {
var systemInfo = wx.getSystemInfoSync()
var contentHeight = systemInfo.windowHeight
this.setData({
contentHeight: contentHeight
})
}
},
/** * A list of methods for a component */
methods: {
play: function(event) {
var that = this
var index = event.currentTarget.dataset.index
this.setData({
playIndex: index
})
},
onScroll: function(event) {
var contentHeight = this.data.contentHeight
var scrollHeight = event.detail.scrollHeight
var scrollTop = event.detail.scrollTop
var scrollPosition = Math.floor(scrollTop + contentHeight/2)
var index = this.getCurrentPlayIndex(scrollPosition, scrollHeight)
var playIndex = this.data.playIndex
if(index != playIndex) {
this.setData({
playIndex: index
})
}
},
getCurrentPlayIndex: function(scrollPosition, scrollHeight) {
var contentHeight = this.data.contentHeight
var listHeight = this.data.listHeight ? this.data.listHeight:0
var top = scrollHeight - listHeight
var current = -1
var videoItems = this.data.videoItems
if(!videoItems || videoItems.length <= 0) {
return -1
}
var offset = top - videoItems[0].top
for(var i=0; i<videoItems.length; i++) {
if(scrollPosition >= (videoItems[i].top + offset) && scrollPosition <= (videoItems[i].bottom + offset)) {
current = i
break
}
}
return current
},
}
})
边栏推荐
- RK3568开发板评测篇(二):开发环境搭建
- leetcode:871. 最低加油次数【以前pat做过 + 最大堆 +贪心】
- [AUTOSAR five methodology]
- Sentry developer contribution Guide - configure pycharm
- 瑞萨电子RZ/G2L开发板上手评测
- AEM: Nanlin fan Ben et al. - plant rhizosphere growth promoting bacteria control soybean blight
- MongoDB系列之MongoDB常用命令
- 1.12 - Instructions
- Linear programming of mathematical modeling (including Matlab code)
- matlab 多普勒效应产生振动信号和处理
猜你喜欢
1.12 - 指令
Arduino开发之按键检测与正弦信号输出
Reading and writing speed of Reza rz/g2l arm development board storage and network measurement
excel IF公式判断两列是否相同
leetcode:871. 最低加油次数【以前pat做过 + 最大堆 +贪心】
瑞萨电子RZ/G2L开发板上手评测
Key detection and sinusoidal signal output developed by Arduino
excel表格计算时间日期的差值,并转化为分钟数
[AUTOSAR I overview]
Leetcode-2280: represents the minimum number of line segments of a line graph
随机推荐
leetcode-934:最短的桥
Sentry developer contribution Guide - configure pycharm
Tensorflow 2.x(keras)源码详解之第十五章:迁移学习与微调
2022 list of manufacturers of Chinese 3D vision enterprises (guided positioning and sorting scenes)
matlab查找某一行或者某一列在矩阵中的位置
Vulkan performance and refinement
测试右移:线上质量监控 ELK 实战
cordova-plugin-device获取设备信息插件导致华为审核不通过
拥抱平台化交付的安全理念
[AUTOSAR 11 communication related mechanism]
The difference between relational database and non relational database
Matlab saves the digital matrix as geospatial data, and the display subscript index must be of positive integer type or logical type. Solve the problem
Data analysis, thinking, law breaking and professional knowledge -- analysis method (I)
[love crash] neglected details of gibaro
飞凌搭载TI AM62x的ARM核心板/开发板首发上市,亮相Embedded World 2022
1038 Recover the Smallest Number
【AutoSAR 一 概述】
Machine learning: numpy version linear regression predicts Boston house prices
First hand evaluation of Reza electronics rz/g2l development board
全志A40i/T3如何通过SPI转CAN