当前位置:网站首页>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
},
}
})
边栏推荐
- Rust ownership (very important)
- Rust string slicing, structs, and enumeration classes
- 合并K个已排序的链表
- AEM: Nanlin fan Ben et al. - plant rhizosphere growth promoting bacteria control soybean blight
- 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
- matlab将数字矩阵保存为地理空间数据出错,显示下标索引必须为正整数类型或逻辑类型,解决
- 1.12 - 指令
- Key detection and sinusoidal signal output developed by Arduino
- Is there a free text to speech tool to help recommend?
- Meaning of Tencent cloud free SSL certificate extension file
猜你喜欢
随机推荐
Basic use of sringcloud & use of component Nacos
Problèmes de configuration lex & yacc & Bison & Flex
【AutoSAR 八 OS】
【爱死机】《吉巴罗》被忽略的细节
用Go+绘制爱心给心爱的她表白
Infrared thermography temperature detection system based on arm rk3568
1038 Recover the Smallest Number
[AUTOSAR five methodology]
[love crash] neglected details of gibaro
瑞萨RZ/G2L 处理器简介|框架图|功耗|原理图及硬件设计指南
Leetcode-241: designing priorities for operational expressions
Inversion de l'intervalle spécifié dans la liste des liens
Solve the cache problem of reactnative using WebView
瑞萨RZ/G2L ARM开发板存储读写速度与网络实测
正确甄别API、REST API、RESTful API和Web Service之间的异同
【AutoSAR 十二 模式管理】
MySQL multi table joint deletion
Leetcode-2280: represents the minimum number of line segments of a line graph
leetcode-2115:从给定原材料中找到所有可以做出的菜
链表中的节点每k个一组翻转