使用uniapp开发多端短视频(用swiper+video去实现)

1.首先我们封装video播放器

     注意:video的层级进行修改在H5中要加入x5-video-player-type="h5-page"属性进行内核处理(目前仅在微信浏览器中处理过),微信小程序IOS的版的可以动态获取video的id进行createVideoContext操作,然而安卓机中并不行,安卓机仅支持一个video的ID去操作createVideoContext

<template>
	<view style="height: 100%;" class="video-fix-box">
		<view style="height: 100%;" v-if="videoUrlStr != ''">
			<!-- #ifdef MP-WEIXIN -->
			<video v-if="phoneType" class="video" id="videoWatch" :src="videoUrl" :controls="controlsType" :loop="true" :show-center-play-btn="false" :show-play-btn="false" @timeupdate="onUpdata" :enable-progress-gesture="false" :enable-play-gesture="false" :muted="mutedType" objectFit="contain" :poster="thumbnailUrl" @loadedmetadata="loadeFn"  @error="videoError" :custom-cache="false" ></video>
			<video v-else class="video" :id="`video${videoId}`" :src="videoUrl" :controls="controlsType" :loop="true" :show-center-play-btn="false" :show-play-btn="false" @timeupdate="onUpdata" :enable-progress-gesture="false" :enable-play-gesture="false" :muted="mutedType" objectFit="contain" :poster="thumbnailUrl" @loadedmetadata="loadeFn"  @error="videoError" :custom-cache="false" ></video>
			<!-- #endif -->
			<!-- #ifdef H5 -->
			<!-- cover -->
			<video class="video" :id="`video${videoId}`" :src="videoUrl" :controls="controlsType" :loop="true" :show-center-play-btn="false" :show-play-btn="false" @timeupdate="onUpdata" :enable-progress-gesture="false"  :enable-play-gesture="false" :muted="mutedType" :objectFit="videoProportion > 1 ? 'contain' : 'cover'" :poster="thumbnailUrl" @error="videoError" x5-video-player-type="h5-page" @loadedmetadata="loadeFn" :webkit-playsinline="true" preload="auto"></video>
			<!-- #endif -->
		</view>
		<view class="tiem-line" :style="{width:newWidthLin}"></view>
	</view>
</template>


<script>
	export default {
		props:{
			userId:{ // 用户id 	
				type:Number,
				default:0
			}, 
			userName:{ // 用户名称
				type:String,
				default:'xxxx'
			},
			userUrl:{ // 用户头像路径
				type:String,
				default:'xxxx'
			},
			title:{ // 视频标题
				type:String,
				default:'xxxx'
			},
			videoUrl:{ // 视频路径
				type:String, 
				default:''
			},
			thumbnailUrl:{ // 视频封面路径
				type:String,
				default:'xxxx'
			},
			videoId:{ // 视频id
				type:Number,
				default:0
			},
			distAnce:{ // 距离
				type:Number,
				default:0
			},
			loveNum:{ // 点赞数量
				type:Number,
				default:0
			},
			shareNum:{ // 转发数量
				type:Number,
				default:0
			},
			commentNum:{ // 评论数量
				type:Number,
				default:0
			},
			playType:{  // 控制播放状态
				type:Boolean,
				default:false
			},
			videoShow:{ // 监听时候跳转页面了
				type:Boolean,
				default:false
			},
			homeInx:{ // 监听home的轮播图是否切换
				type:Number,
				default:0
			},
			controlsType:{ // 是否暂时原生控制条
				type:Boolean,
				default:false
			},
			videoInx:{ // 视频列表索引
				type:Number
			},
			presentInx:{ // spewr目前索引
				type:Number
			},
			phoneType:{ // 判断小程序手机类型是否为安卓手机
				type:Boolean
			},
			mutedType:{ // 控制音量的
				type:Boolean
			}
		},
		data() {
			return {
				baseImgUrl:'基准路径',
				time:0,
				duration:0,
				PlatFormType:false,
				videoWidth:0,
				videoHeight:0
			}
		},
		computed:{
			newWidthLin(){
				let newWidth = (this.time / this.duration).toFixed(2) * 100
				return `${newWidth}%`
			},
			videoUrlStr(){
				return this.videoUrl
			},
			videoProportion(){
				let newTion = this.videoWidth / this.videoHeight
				return newTion
			}
		},
		methods: {
			onUpdata(e){ // 计算播放进度条
				this.time =  e.detail.currentTime
				this.duration = e.detail.duration
			},
			videoError(e){
			},
			loadeFn(e){ // 真机才会显示出来 --- 后面需要处理
				// uni.showToast({
				//     title: '高度' + e.detail.height + ',宽度:' + e.detail.width,
				//     duration: 3000
				// });
				this.videoWidth = e.detail.width
				this.videoHeight = e.detail.height
			}
		}, 	
		mounted() {
			// #ifdef H5
			this.videoContext = uni.createVideoContext(`video${this.videoId}`,this)
			// #endif
			// #ifdef MP-WEIXIN
			if(this.phoneType){
				this.videoContext = uni.createVideoContext('videoWatch',this)
			}else{
				this.videoContext = uni.createVideoContext(`video${this.videoId}`,this)
			}
			// #endif
		},
		watch:{
			videoId:{
				immediate: true,
				handler(newVal,oldVal){
					if(this.playType && this.phoneType){
						this.videoContext = uni.createVideoContext('videoWatch',this)
					}
				}
			},
			videoShow(newval,oldval){	
				if(this.homeInx === 0){ // 判断是不是在看视频的时候跳转的---这里可能到时还需要做其他处理
					if(newval){
						if(this.videoInx === this.presentInx){
							this.videoContext.play()
							this.$emit('play',true)
						}
					}else{
						if(this.videoContext != undefined){
							this.videoContext.pause()
						}
						this.$emit('pause',false)
					}
				}
			},
			playType:{
				immediate: true,
				handler(newVal,oldVal){
					if(newVal){
					 	this.videoContext.play()
					}else{
						if(this.videoContext != undefined){
							this.videoContext.pause()
						}
					}
				}
			},
			homeInx(newval,oldval){
				if(newval === 1){
					if(this.playType){
						this.$emit('tabPause',false)
					}
				}else{
					if(!this.playType){
						this.$emit('tabPlay',false)
					}
				}
			}
			
		}
	}
</script>

<style lang="scss">
	.video{
		height: 100%;
	}
	.video-fix-box{		
		position: relative;
		.video{
			z-index: -1;
			width: 100%;
		}
		.tiem-line{	
			position: absolute;
			z-index: 888;
			bottom: 0;
			left: 0;
			height: 4rpx;
			background-color: #fff;
		}
	}
</style>

 2.使用封装好的video播放器

<swiper :vertical="true" :current="currentInx" @change="swiPerFn" style="height: 100%;">
			<swiper-item v-for="(item, inx) in videoList" :key="inx" :duration="200">
                <!-- #ifdef H5 -->
                // 去绝对值==1的,当前视频上下的视频都会显示
                <view v-if="Math.abs(inx - currentInx) <= 1" style="height: 100%;">
						<public-video :src="视频路径" ...></public-video>
                <view v-else></view>
				<!-- #endif -->
                <!-- #ifdef MP-WEIXIN-->
                    // PlatFormType用来判断进行机型,app入口文件可以获取存入本地等其他
                    // 微信小程序中ios系统  
                     <view v-if="!PlatFormType">
                        // 去绝对值==1的,当前视频上下的视频都会显示(取多后性能会很卡)
                        <view v-if="Math.abs(inx - currentInx) <= 1" style="height: 100%;">
						   <public-video :src="视频路径" ...></public-video>
                        </view>
                        <view v-else></view>
                     </view>
                     // 微信小程序中安卓系统
                     <view v-else>
                        // 只显示当前索引的视频,当前视频上下的用封面图或者骨架图(避免部分安卓机再看视频的时候跳去其他页面不能调用video中的pause暂停视频)
                        <view v-if="inx === currentInx" style="height: 100%;">
						   <public-video :src="视频路径" ...></public-video>
                        </view>
                        <view v-else-if="Math.abs(inx - currentInx) === 1" style="height: 100%;">
							<image src="骨架图路径" mode="" class="video-img"></image>
						</view>
                        <view v-else></view>
                     </view>  
				<!-- #endif -->
            </swiper-item>
<swiper

 

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
uniapp中,可以通过使用swiper和view组件来实现左右tab切换,并且让内容高度自适应。以下是一个示例代码: ``` <template> <view class="container"> <swiper autoplay="false" current="{{ current }}" class="swiper" duration="300" skip-hidden-item-layout="true" @change="swiperChange" > <swiper-item> <view class="tab-item" :class="{active: currentTab === 0}" @tap="changeTab(0)">Tab 1</view> </swiper-item> <swiper-item> <view class="tab-item" :class="{active: currentTab === 1}" @tap="changeTab(1)">Tab 2</view> </swiper-item> <swiper-item> <view class="tab-item" :class="{active: currentTab === 2}" @tap="changeTab(2)">Tab 3</view> </swiper-item> </swiper> <view class="content"> <view class="tab-content" :class="{active: currentTab === 0}" style="height: {{tabHeight[0]}}px"> Content 1 </view> <view class="tab-content" :class="{active: currentTab === 1}" style="height: {{tabHeight[1]}}px"> Content 2 </view> <view class="tab-content" :class="{active: currentTab === 2}" style="height: {{tabHeight[2]}}px"> Content 3 </view> </view> </view> </template> <script> export default { data() { return { current: 0, currentTab: 0, tabHeight: [0, 0, 0] }; }, methods: { swiperChange(e) { this.currentTab = e.detail.current; }, changeTab(index) { this.currentTab = index; this.current = index; } }, mounted() { const query = uni.createSelectorQuery().in(this); query.selectAll(".tab-content").boundingClientRect(rects => { this.tabHeight = rects.map(rect => rect.height); }).exec(); } }; </script> <style> .container { display: flex; flex-direction: column; height: 100vh; } .swiper { height: 80rpx; margin-top: 20rpx; } .tab-item { height: 80rpx; line-height: 80rpx; text-align: center; } .tab-item.active { color: #007aff; border-bottom: 3rpx solid #007aff; } .content { flex: 1; overflow: hidden; } .tab-content { position: absolute; left: 0; top: 0; width: 100%; overflow-y: scroll; -webkit-overflow-scrolling: touch; transition: height 0.3s; } .tab-content.active { height: auto; } </style> ``` 在这个示例中,我们使用swiperswiper-item组件来实现左右tab切换,使用view组件来展示每个tab对应的内容。我们监听swiper的change事件,根据current属性来更新当前选中的tab,同时也更新currentTab属性。在每个tab-content的样式中,我们设置了height为auto,这样可以让内容自适应高度。在mounted生命周期中,我们使用uni.createSelectorQuery()获取每个tab-content的高度,保存在tabHeight数组中,然后在模板中使用style绑定动态高度,实现高度自适应。
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值