Uniapp 之renderjs解决swiper+多个video卡顿问题
一、效果图
二、示例代码
test.vue
<template> <view style="" :style="{height: windowHeight+'px'}"> <swiper class="video-swiper" vertical @change="swiperChange" :current="current" @animationfinish="swiperFinish"> <swiper-item v-for="(item,index) in list" :key="index" style="position: relative;"> <MyVideo :fistId="list[0].itemid" :item="item" :isPlay="!isShow && videoId == item.itemid" @onEnded="endVideo(item.itemid)" /> <view v-if="isShow" style="z-index:99;position: absolute;width:100%;height:100%;top:0;left:0;display:flex; justify-content:center; align-items:center;"> <image @click.stop="plays(item.itemid,index)" src="@/static/bofang.png" style="width: 40px;height: 40px;"></image> </view> <view class="abs video-info-box"> <view class="video-info"> <view class="f-title c-base ">@样子公司</view> <view class="f-paragraph c-base mt-md">{{item.title}}</view> </view> </view> </swiper-item> </swiper> </view> </template> <script> import MyVideo from '@/components/my-video/my-video.vue' export default { components: { MyVideo }, data() { return { windowHeight: uni.getSystemInfoSync().windowHeight, list: [{ itemid: 1, url: '/file/upload/202508/01/094826971.mp4', title: '视频一' }, { itemid: 2, url: '/file/upload/202508/01/090055511.mp4', title: '视频二' }, { itemid: 3, url: '/file/upload/202508/01/090409611.mp4', title: '视频三' } ], videoContexts: [], isShow: false, videoIndex: null, videoId: null, current: 0, first_id: 0 } }, onLoad() { }, methods: { swiperChange(e) { console.log(e) let { current } = e.detail this.current = current if (current != this.videoIndex) { this.endVideo(this.videoId, 'swiper') } }, swiperFinish(e) { console.log(e) let { current } = e.detail let item = this.list[current] console.log(item) this.plays(item.itemid, current) }, plays(id, index) { // #ifndef APP let videoContext = uni.createVideoContext(`Video${id}`, this); videoContext.play() // #endif this.videoId = id this.videoIndex = index this.isShow = false this.autoplaySwiper = false }, //当video播放结束得时候 进行初始化,恢复轮播 endVideo(id, type) { // #ifndef APP let videoContext = uni.createVideoContext(`Video${id}`, this); videoContext.pause() // #endif this.isShow = true this.videoIndex = null this.videoId = null this.autoplaySwiper = true if (!type) { setTimeout(v => { this.current++ }, 500) } }, } } </script> <style> .video-swiper { width: 100%; height: 100% } .video_item { height: 100%; width: 100%; } .video-info-box { width: 500rpx; height: auto; display: inline-block; position: absolute; left: 32rpx; bottom: 100rpx; z-index: 99999999; } </style>
my-video.vue
<template> <view class="myVideo_view" v-html="innerHtml" :fid="fistId" :change:fid="MyVideo.setFid" :id="id" :change:id="MyVideo.updateId" :isPlay="isPlay" :change:isPlay="MyVideo.handelPlay" ></view> </template> <script> export default { props: { item: { type: Object, default: () => ({}), }, // 添加控制播放和暂停的prop isPlay: { type: Boolean, default: true, }, fistId: { type: Number, default: 0 } }, computed: { id() { return this.item.itemid } }, data() { return { innerHtml: '', }; }, created() { this.initVideoHtml(); }, methods: { isHttpOrHttps(url) { const regex = /^(http|https):\/\//; return regex.test(url); }, initVideoHtml() { let { url } = this.item let bool = this.isHttpOrHttps(url) if(!bool) { url = plus.io.convertLocalFileSystemURL(url); } this.innerHtml = `<video class="swiper-video" id="Video${this.item.itemid}" src="${url}" width="100%" height="100%" style="object-fit: contain;" autoplay/>`; }, // 通知父组件播放完成 ended() { this.$emit('onEnded') } }, }; </script> <script module="MyVideo" lang="renderjs"> export default { data() { return { id: '', fid: '', video: null, } }, computed: { videoId() { return 'Video' + this.id } }, mounted() { this.initVideoElement() }, methods: { initVideoElement() { let video = document.getElementById(this.videoId) this.video = video video.addEventListener('loadedmetadata', () => { this.video.play().then(res => { //第一个视频不用暂停 if(this.fid==this.id) { return false } this.video.pause() }) }) video.addEventListener('ended', () => { this.video.pause() this.$ownerInstance.callMethod('ended') }) }, handelPlay(isPlay) { if(!this.video) return isPlay ? this.video.play() : this.video.pause() }, updateId(id) { this.id = id }, setFid(fid) { this.fid = fid } } } </script> <style scoped> .myVideo_view { height: 100%; border-radius: 10rpx; overflow: hidden; background-color: #000; } </style>