前言

仿抖音截图
在这里插入图片描述

在这里插入图片描述

基于uniapp模仿抖音的视频播放,其核心就是播放器,因此记录一下实现该功能的组件,我喜欢组件化开发,就放重点的一些组件,可以在下面的代码中学到父组件调用子组件的方法,父组件向子组件传值,子组件向父组件传值等操作

在这里插入图片描述
组件化开发

videoList.vue //主要组件

<template>
	<view class="videoList">
		<view class="swiper-box">
			<swiper class="swiper"  :vertical="true" @change="changeplay" @touchstart="touchStart" @touchend="touchEnd">
				<swiper-item v-for="(item,index) in videos" :key="item.id">
					<view class="swiper-item"  style="color: #000000;">
						<video-player @changeClick='changeClick' ref="player" :video="item" :index="index"></video-player>
					</view>
					<view class="listleftbox">
						<list-left></list-left>
					</view>
					<view class="listrightbox">
						<list-right ref="right"></list-right>
					</view>
				</swiper-item>
			</swiper>
		</view>
		
	</view>
</template>

<script>
	import videoPlayer from './videoPlayer.vue'
	import listLeft from './listLeft.vue'
	import listRight from './listRight.vue'
	var time = null
	export default {
		props:['list'],
		name:"videoList",
		components:{
			videoPlayer,
			listLeft,
			listRight
		},
		data() {
			return {
				videos:[],
				pageStatrY:0,
				pageEndY:0,
				page:0
			};
		},
		//监听传过来的list
		watch:{
			//当list发生改变 就触发这个方法 所以用watch
			list(){
				this.videos = this.list
				console.log(this.videos)
			}
		},
		methods:{
			changeClick(){
				//双击点赞 调用子组件listright的方法
				this.$refs.right[0].change()
			},
			//上下滑动触发事件
			changeplay(res){
				clearTimeout(time)
				this.page = res.detail.current
				time=setTimeout(()=>{
					if(this.pageStatrY < this.pageEndY){
						console.log('向上滑动')
						setTimeout(()=>{
							this.$refs.player[this.page].player()
						},20)
						
						this.$refs.player[this.page+1].pause()
						this.pageStatrY=0
						this.pageEndY=0
					}else{
						console.log('向下滑动')
						setTimeout(()=>{
							this.$refs.player[this.page].player()
						},20)
						
						this.$refs.player[this.page-1].pause()
						this.pageStatrY=0
						this.pageEndY=0
					}
				},1)	
			},
			//获取向下滑动的值
			touchStart(res){
				
				this.pageStatrY = res.changedTouches[0].pageY
				console.log(this.pageStatrY)
			},
			//获取向上滑动的值
			touchEnd(res){		
				
				this.pageEndY = res.changedTouches[0].pageY
				console.log(this.pageEndY)
			}
		}
	}
</script>

<style>
.videoList{
	height: 770px;
	width: 100%;
}
.swiper-box{
	height: 100%;
	width: 100%;
}
.swiper{
	height: 100%;
	width: 100%;
}
.swiper-item{
	height: 100%;
	width: 100%;
	z-index:19;
}
.title{
	color: #FFFFFF;
}
/deep/.listleftbox{
	z-index:20;
	position: absolute;
	bottom: 50px;
	left: 10px;
}
/deep/.listrightbox{
	z-index:20;
	position: absolute;
	bottom: 50px;
	right: 10px;
	color: #FFFFFF;
}


</style>

videoPlayer.vue //存放视频的组件
下面存放视频的地址可以自己在Apache的服务器上自己存放好视频
<template>
	<view class="videoPlayer">	
		<video 
		id="myVideo" 
		class="video" 
		:controls="false" 
		:src="'http://192.168.112.1:80/video/'+video.src" 
		:loop="true" 
		:autoplay="autoplay"
		controls
		@click="click"></video>
	</view>
</template>

<script>
	var timer=null
	export default {
		props:['video','index'],
		data() {
			return {
				play:false,
				dblClick:false,
				autoplay:false
			};
		},
		mounted(){
			this.videoContext=uni.createVideoContext('myVideo',this)
		},
		methods:{
			click(){
				clearTimeout(timer)
				this.dblClick=!this.dblClick
				timer=setTimeout(()=>{
					if(this.dblClick){ //判断是单击 即为true
						//单击
						if(this.play===false){
							this.playThis()
						}else{
							this.pause()
						}
					}else{
						//双击
						this.$emit('changeClick') //向父组件传递一个事件
					}
					this.dblClick=false //点击后重置状态 重置为false
				},300)
			},
			player(){
				//从头播放视频
				if(this.play===false){
					this.videoContext.seek(0)
					this.videoContext.play()
					this.play=true
				}
			},
			pause(){
				//暂停视频
				if(this.play===true){
					this.videoContext.pause()
					this.play=false
				}
			},
			playThis(){
				//播放当前视频
				if(this.play===false){
					this.videoContext.play()
					this.play=true
				}
			},
			//首个视频自动播放
			atuo(){
				//首个视频自动播放
				if(this.index===0){
					this.autoplay=true
				}
			}
		},
		created() {
			this.atuo()
		}
	}
	
</script>
 
<style>
.videoPlayer{
	height: 100%;
	width:100%;
}
.video{
	height: 100%;
	width:100%;
	z-index: 1;
}
</style>

listRight.vue //页面右组件的内容
<template>
	<view class="listright">
		<view class="author-img">
			<image mode="widthFix" src="../static/img/author.jpg" class="img"></image>
			<view class="iconfont icon-jiahao add" v-show="show" @click="hide"></view>
		</view>
		<view class="iconfont icon-xin right-box" :style="color" @click="changeColor">
			
		</view>
		<view class="number">
			123
		</view>
		<view class="iconfont icon-53pinglun- right-box">
			
		</view>
		<view class="number">
			521
		</view>
		<view class="iconfont icon-fenxiang right-box">
			
		</view>
		<view class="number">
			521
		</view>
		<view class="around">
			<image src="../static/logo.png" class="img"></image>
		</view>
	</view>
</template>

<script>
	export default {
		name:"listright",
		data() {
			return {
				show:true,
				color:''
			};
		},
		methods:{
			hide(){
				this.show =false
			},
			//点击爱心变红(即点赞)或者变白(取消点赞)
			changeColor(){
				this.color = this.color === ''?'color:red;':''
			},
			//双击点赞
			change(){
				this.color = "color:red;"
			}
		}
	}
</script>

<style>
.listright{
	width: 50px;
	margin: 0 auto;
}
.author-img{
	width: 50px;
	height: 50px;
	border-radius: 50%;
	border: 3px solid #FFFFFF;
	position: relative;
}
.right-box{
	width: 50px;
	height: 40px;
	margin-top: 13px;
	text-align: center;
	line-height: 40px;
	color: #FFFFFF;
	font-size: 30px;
}
.img{
	width: 50px;
	height: 50px;
	border-radius: 50%;
}

.number{
	font-size: 10px;
	text-align: center;
	color: #FFFFFF;
}
.around{
	margin-top: 15px;
	width: 50px;
	height: 50px;
	animation: rotate 1.5s linear 0.2s infinite;
}
.add{
	background-color: red;
	position: absolute;
	bottom: -9px;
	left:16px;
	text-align: center;
	line-height: 18px;
	color: #FFFFFF;

}

@keyframes rotate{
	0%{
		transform: rotate(0deg);
	}
	100%{
		transform: rotate(360deg);
	}
}
</style>

listLeft.vue //左边组件的内容
<template>
	<view class="listLeft">
		<view class="author">
			sina
		</view>
		<view class="title">
			nihaonihaonihaonihaonihaonih
		</view>
		<view class="box">
			<view class="music">
				你要的爱你要的爱你要的爱你要的爱你要的爱
			</view>
		</view>
		
	</view>
</template>

<script>
	export default {
		name:"list",
		data() {
			return {
				
			};
		}
	}
</script>

<style>
.listLeft{
	height: 150px;
	margin-left: 10px ;
	color: #FFFFFF;
	width: 150px;
	
}

.author{
	height: 35px;
	line-height: 35px;
	font-size: 17px;
}

.title{

	line-height: 20px;
	font-size: 15px;
	width: 100%;
	word-wrap: break-word;
}
.box{
	width: 100px;
	overflow: hidden;
}
.music{
	height: 35px;
	line-height: 35px;
	font-size: 15px;
	width: 200px;
	animation: music 4s linear 0.2s infinite;
}

@keyframes music{
	0%{
		transform: translate3d(80%,0,0);
	}
	100%{
		transform: translate3d(-80%,0,0);
	}
}
</style>

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐