当前位置:网站首页>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
},
}
})
边栏推荐
- Hdu3507 (slope DP entry)
- Leetcode-241: designing priorities for operational expressions
- Leetcode-849: maximum distance to the nearest person
- 1038 Recover the Smallest Number
- matlab查找某一行或者某一列在矩阵中的位置
- MongoDB系列之MongoDB常用命令
- Illustrated network: what is virtual router redundancy protocol VRRP?
- The difference between tail -f, tail -f and tail
- [daily training] 871 Minimum refueling times
- leetcode-2280:表示一个折线图的最少线段数
猜你喜欢
电话网络问题
Is there a free text to speech tool to help recommend?
Unity learns from spaceshooter to record the difference between fixedupdate and update in unity for the second time
excel表格计算时间日期的差值,并转化为分钟数
What is needed to develop a domestic arm intelligent edge computing gateway
1.12 - Instructions
Test shift right: Elk practice of online quality monitoring
【AutoSAR 九 C/S原理架构】
[AUTOSAR + IO Architecture]
FPGA - 7 Series FPGA internal structure clocking -04- multi area clock
随机推荐
[AUTOSAR nine c/s principle Architecture]
leetcode-2280:表示一个折线图的最少线段数
数据分析思维分析犯法和业务知识——分析方法(一)
测试右移:线上质量监控 ELK 实战
How to systematically learn machine learning
Leetcode-934: the shortest Bridge
【C语言】分支和循环语句(上)
拥抱平台化交付的安全理念
leetcode-2115:从给定原材料中找到所有可以做出的菜
Teach you JDBC hand in hand -- structure separation
Deep analysis of data storage in memory
Unity learns from spaceshooter to record the difference between fixedupdate and update in unity for the second time
Liad: the consumer end of micro LED products is first targeted at TVs above 100 inches. At this stage, it is still difficult to enter a smaller size
leetcode-871:最低加油次数
2022.2.14 resumption
[AUTOSAR VI description document]
Test shift right: Elk practice of online quality monitoring
Reading and writing speed of Reza rz/g2l arm development board storage and network measurement
[AUTOSAR eight OS]
Meaning of Tencent cloud free SSL certificate extension file