uniapp小视频项目:关注页面开发

116 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第11天,点击查看活动详情

1、关注页面开发

首先添加跳转,修改 nav.vue 给首页和关注增加跳转

<navigator open-type="switchTab" url="/pages/index/index" class="tab-box">
	首页
</navigator>

<navigator open-type="switchTab" url="/pages/follow/follow" class="tab-box">
	关注
</navigator>

修改 follow.vue

<template>
	<view class="follow">
		<follow-nav></follow-nav>
		<tab></tab>
	</view>
</template>

<script>
	import followNav from '../../components/followNav.vue'
	import tab from '../../components/tab.vue'
	export default {
		components:{
			followNav,
			tab
		}
	}
</script>

<style>
.follow{
	width: 100%;
	height: 100%;
	background: #000000;
}
</style>

增加 follow-nav.vue,由于和首页头部很像,所以我们直接复制改一下

<template>
	<view class="followNav">
		<view class="iconfont icon-xiangji icon">
			<text class="icon-text">随拍</text>
			</view>
		<view class="middle">
			<navigator open-type="switchTab" class="text" url="/pages/index/index">关注</navigator>
			<navigator open-type="navigate" class="text" url="/pages/city/city">好友</navigator>
		</view>
	</view>
</template>

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

<style>
.followNav{
	width: 100%;
	height: 35px;
	line-height: 35px;
	position: fixed;
	top: 25px;
	left: 0;
	margin: 0 auto;
	z-index: 20;//只要比19大,就显示在视频上方
}
.icon{
	position: absolute;
	left: 5px;
	top: 0;
	color: #ffffff;
	width: 20%;
	text-align: center;
	font-size: 20px;
}
.middle{
	text-align: center;
}
.text{
	display: inline;
	color: #FFFFFF;
	margin: 0 10px;
	font-size: 15px;
}
.icon-text{
	font-size: 15px;
	margin-left: 5px;
}
</style>

目前效果:

在这里插入图片描述

2、关注页面完善

先看效果:

在这里插入图片描述 修改 follow.vue

<template>
	<view class="follow">
		<follow-nav></follow-nav>
		<follow-list></follow-list>
		<tab></tab>
	</view>
</template>

<script>
	import followNav from '../../components/followNav.vue'
	import tab from '../../components/tab.vue'
	import followList from '../../components/followList.vue'
	export default {
		components:{
			followNav,
			tab,
			followList
		},
		data() {
			return {
				
			}
		},
		methods: {
			
		}
	}
</script>

<style>
.follow{
	width: 100%;
	height: 100%;
	background: #000000;
}
</style>

新建 followList.vue

<template>
	<view class="followList">
		<view class="item">
			<view class="top">
				<view class="image-box">
					<image class="img" src="../static/profile.webp"></image>
				</view>
				<view class="author-name">
					张三
				</view>
				<view class="iconfont icon-gengduo share">
					
				</view>
			</view>
			<view class="title">
				我爱学习
			</view>
			<view class="video-box">
				<video class='video' objectFit="cover" src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"></video>
				<view class="music-box">
					<view class="music">
						今天好生气啊我好后悔搭理那条疯狗
					</view>
				</view>
			</view>
			<view class="box">
				<view class="left">3-15</view>
				<view class="right">
					<view class="iconfont icon-xin icon">
						<text class="text"></text>
					</view>
					<view class="iconfont icon-pinglun icon"><text class="text">评论</text></view>
					<view class="iconfont icon-fenxiang icon"><text class="text">分享</text></view>
				</view>
			</view>
			<view class="comment">
				<view class="number">
					4.2w评论过
				</view>
				<view class="comment-box">
					<view class="iconfont icon-icon-checkin icon-pen"></view>
					<input class="input-box" type="text" placeholder="添加评论..." />
				</view>
			</view>
		</view>
	</view>
</template>

<script>
	export default {
		name: "followList",
		data() {
			return {

			};
		}
	}
</script>

<style>
	.followList {
		width: 100%;
		background: #000000;
		padding-bottom: 50px;
		margin-top: 10px;
	}

	.item {
		padding: 0 15px;
	}

	.top {
		height: 50px;
	}

	.image-box {
		float: left;
	}

	.img {
		width: 35px;
		height: 35px;
		border-radius: 50%;
	}

	.author-name {
		float: left;
		font-size: 14px;
		height: 35px;
		line-height: 35px;
		color: #ffffff;
		margin-left: 10px;
	}

	.share {
		float: right;
		font-size: 25px;
		margin-right: 5px;
		height: 35px;
		line-height: 35px;
		color: #ffffff;
	}

	.title {
		width: 100%;
		font-size: 13px;
		height: 25px;
		line-height: 25px;
		color: #ffffff;
	}

	.video-box {
		width: 100%;
		height: 350px;
		position: relative;
	}

	.video {
		width: 80%;
		height: 100%;
		z-index: 19;
	}
	.music-box{
		z-index: 20;
		position: absolute;
		bottom: 10px;
		left: 10px;
		width: 100px;
		overflow: hidden;
	}
	.music{
		color: #ffffff;
		font-size: 14px;
		width:250px ;
		animation: music 4s linear infinite;
	}
	.box {
		height: 25px;
		margin-top: 25px;

	}

	.left {
		float: left;
		font-size: 11px;
		height: 25px;
		line-height: 25px;
		color: #AAAAAA;
	}

	.right {
		float: right;
		height: 25px;
	}

	.icon {
		float: right;
		color: #ffffff;
		font-size: 18px;
		margin-left: 10px;
	}

	.text {
		padding: 0 5px;
		font-size: 13px;
	}
	.comment{
		width: 100%;
	}
	.number{
		width: 100%;
		height: 25px;
		font-size: 15px;
		line-height: 15px;
		color: #AAAAAA;
		margin:10px 0
	}
	.comment-box{
		position: relative;
	}
	.icon-pen{
		height: 25px;
		color: #ffffff;
		position:absolute;
		left: 0;
		top: 0;
	}
	.input-box{
		margin-left: 28px;
		font-size: 15px;
	}
	@keyframes music{
		0%{
			transform: translate3d(80%,0,0);
		}
		100%{
			transform: translate3d(-80%,0,0);
		}
	}
</style>

3、创建好友页面

创建好友页面 friend.vue

<template>
	<view class="friend">
			<follow-nav :page="page"></follow-nav>
			<follow-list :list="list"></follow-list>
			<tab></tab>
	</view>
</template>

<script>
	import followNav from '../../components/followNav.vue'
	import tab from '../../components/tab.vue'
	import followList from '../../components/followList.vue'
	export default {
		components:{
			followNav,
			tab,
			followList
		},
		data() {
			return {
				page:'friend',
				list:[]
			}
		},
		methods: {
			getVideo() {
				uni.request({
					url:"http://127.0.0.1:8080/downloads/video.json",
					success: (res) => {
						this.list = res.data.list
					}
				})
			}
		},
		created() {
			this.getVideo()
		}
	}
</script>

<style>
.friend{
	width: 100%;
	height: 100;
	background: #000000;
}
</style>

设置为 tabbar 页面,修改 pages.json

"tabBar": {
		"list": [
			......
			{
				"pagePath": "pages/friend/friend",
				"text": "好友"
			}
		]
	}

friend.vue 页面中,created 后,请求到视频数据赋值给 list,然后传给子组件 follow-list

follow-list 中接收 list,动态渲染页面数据

<template>
	<view class="followList">
		<view class="item" v-for="item in list" :key="item.id">
			<view class="top">
				<view class="image-box">
					<image class="img" src="../static/profile.webp"></image>
				</view>
				<view class="author-name">
					{{item.author}}
				</view>
				<view class="iconfont icon-gengduo share">
					
				</view>
			</view>
			<view class="title">
				{{item.title}}
			</view>
			<view class="video-box">
				<video class='video' objectFit="cover" :src="item.src"></video>
				<view class="music-box">
					<view class="music">
						今天好生气啊我好后悔搭理那条疯狗
					</view>
				</view>
			</view>
			<view class="box">
				<view class="left">3-15</view>
				<view class="right">
					<view class="iconfont icon-xin icon">
						<text class="text"></text>
					</view>
					<view class="iconfont icon-pinglun icon"><text class="text">评论</text></view>
					<view class="iconfont icon-fenxiang icon"><text class="text">分享</text></view>
				</view>
			</view>
			<view class="comment">
				<view class="number">
					{{item.commentNumber}}评论过
				</view>
				<view class="comment-box">
					<view class="iconfont icon-icon-checkin icon-pen"></view>
					<input class="input-box" type="text" placeholder="添加评论..." />
				</view>
			</view>
		</view>
	</view>
</template>

<script>
	export default {
		props:['list'],
		name: "followList",
		data() {
			return {

			};
		}
	}
</script>

......

因为好友页面和关注页面类似,所以我们在顶部加一个下划线区分到底显示在哪个页面。friend.vue 向 follow-nav.vue 中传一个 page 来标识本页面

<follow-nav :page="page"></follow-nav>

data() {
	return {
		page:'friend',
		list:[]
	}
}

同样 follow.vue 也同样传一个标识来标识本页面

<follow-nav :page="page"></follow-nav>
data() {
	return {
		page: 'follow',
		list:[]
	}
}

follow-nav.vue 中接收 page 这个参数,根据参数不同改变下划线样式

<template>
	<view>
		<view class="followNav">
			<view class="iconfont icon-xiangji icon">
				<text class="icon-text">随拍</text>
			</view>
			<view class="middle">
				<navigator open-type="switchTab" class="text" url="/pages/follow/follow" :style="follow">关注</navigator>
				<navigator open-type="switchTab" class="text" url="/pages/friend/friend" :style="friend">好友</navigator>
			</view>
		</view>
		<view class="ground"></view>
	</view>
</template>

<script>
	export default {
		props: ['page'],
		name: "followNav",
		data() {
			return {
				follow: '',
				friend: ''
			};
		},
		mounted() {
			if (this.page === "friend") {
				this.friend = "border-bottom: 2px solid #F0AD4E"
			} else {
				this.follow = "border-bottom: 2px solid #F0AD4E"
			}
			console.log(this.page);
		}
	}
</script>
......

看下效果:

在这里插入图片描述

4、关注页面动态播放视频

当进行上下滑动时,只有显示在屏幕中的视频播放,其他视频暂停,要实现这个功能,我们在 follow-list.vue 中增加 scrollview

<template>
	<view class="followList">
		<scroll-view style="height: 100%;" scroll-y="true" @scroll="scroll">
			......
		</scroll-view>
	</view>
</template>

<script>
	export default {
		props: ['list'],
		name: "followList",
		data() {
			return {

			};
		},
		methods:{
			scroll(res){
				console.log(res);
			}
		}
	}
</script>

<style>
	//修改父级高度为 100%,同时为 item 设置一个固定的高度
	.followList {
		width: 100%;
		background: #000000;
		padding-bottom: 50px;
		margin-top: 10px;
		height: 100%;
	}

	.item {
		padding: 0 15px;
		height: 550px;
	}
	......
</style>

在滚动时执行 scroll 方法,打印里边的参数,其中 detail.scrollTop 为距离顶部的距离 在这里插入图片描述 然后除以 550,算出当前处于第几个视频。为了修正距离,给 scrollTop 加上了 150

methods:{
	scroll(res){
		const index = Math.floor((res.detail.scrollTop+150)/550)
		console.log(index);
	}
}

然后把视频封装成一个组件,新建 followPlayer.vue,把 follow-list 中的 video 和相关样式放到 followPlayer 中

<template>
	<view class="followPlayer">
		<video id="myVideo" class='video' loop="true" objectFit="cover" :src="item.src" :controls="false"></video>
	</view>
</template>

<script>
	export default {
		props: ["item", "index"],
		name: "followPlayer",
		data() {
			return {
				isPlay: false
			};
		},
		onReady() {
			this.videoContext = uni.createVideoContext("myVideo", this)
			if (this.index == 0) {
				this.play()
			}
		},
		methods: {
			play() {
				if (this.isPlay === false) {
					this.videoContext.play()
				}
				this.isPlay = true
			},
			pause() {
				if (this.isPlay === true) {
					this.videoContext.pause()
				}
				this.isPlay = false
			}
		}
	}
</script>

<style>
	.followPlayer {
		width: 100%;
		height: 100%;
	}

	.video {
		width: 80%;
		height: 100%;
		z-index: 19;
	}
</style>

然后需要在 followList 中调用子组件 followPlayer 中方法

<template>
	<view class="followList">
		<scroll-view style="height: 100%;" scroll-y="true" @scroll="scroll">
			
				......
				<view class="video-box">
					<follow-player ref="player" :index="index" :item="item"></follow-player>
					<view class="music-box">
						<view class="music">
							今天好生气啊我好后悔搭理那条疯狗
						</view>
					</view>
				</view>
				......	
		</scroll-view>
	</view>
</template>

<script>
	import followPlayer from './followPlayer.vue'
	var time = null
	export default {
		components: {
			followPlayer
		},
		props: ['list'],
		name: "followList",
		data() {
			return {
				index : 0
			};
		},
		methods: {
			scroll(res) {
				clearTimeout()
				time = setTimeout(()=>{
					const index = Math.floor((res.detail.scrollTop + 150) / 550)
					this.index = index
				},100)
			}
		},
		watch:{
			//只有index值发生改变才执行
			index(){
				if (this.index >= 0 && this.index < this.list.length) {
					this.$refs.player[this.index].play()
				}
				if ((this.index - 1) >= 0 && (this.index - 1) < this.list.length) {
					this.$refs.player[this.index - 1].pause()
				}
				if ((this.index + 1) >= 0 && (this.index + 1) < this.list.length) {
					this.$refs.player[this.index + 1].pause()
				}
			}
		}
	}
</script>
......

最后在每个视频上放一个播放或暂停的按钮

<template>
	<view class="followPlayer">
		<video id="myVideo" class='video' loop="true" objectFit="cover" :src="item.src" :controls="false"></video>
		<cover-view class="iconfont icon-bofang icon" @click="click"></cover-view>
	</view>
</template>
<script>
	export default {
		......
		methods: {
			......
			click() {
				if (this.isPlay == true) {
					this.videoContext.pause()
					this.isPlay = false
				} else {
					this.videoContext.play()
					this.isPlay = true
				}
			}
		}
	}
</script>

<style>
	......
	.video {
		width: 80%;
		height: 100%;
		z-index: 19;
		position: relative;
	}

	.icon {
		position: absolute;
		bottom: 10px;
		right: 10px;
		color: #ffffff;
		font-size: 20px;
	}
</style>

查看最终效果:

在这里插入图片描述