Uniapp 之renderjs解决swiper+多个video卡顿问题

发布于:2025-08-18 ⋅ 阅读:(14) ⋅ 点赞:(0)

一、效果图

image

二、示例代码

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>
翻译图片
中文
英文

网站公告

今日签到

点亮在社区的每一天
去签到