上篇文章,咱们已经实现了首页的头部导航栏组件、底部的tabBar导航栏组件、中间的视频列表组件以及视频列表组件中的视频播放组件,传入视频列表渲染后已经能够上下滑动进行视频切换和播放,接下来咱们将完成首页的剩余部分, 左侧信息栏组件、 右侧图标栏组件,以及 完善视频切换动画、 播放控制等功能。
左侧的信息栏组件,主要分三块: 做者名、 视频标题名、 音乐名。这个左侧信息栏信息是和当前播放视频相关联的,因此应该在循环视频列表的时候,将左侧信息栏组件一块儿渲染出来,因此 左侧信息栏组件应该加到<swiper-item>中。
// components/list-left.vuesegmentfault
<template> <view class="list-left"> <view class="author"> @祝晓晗 </view> <view class="title"> 妈呀,遇到老同窗了,缘分呐! @老丈人说车 @抖音小助手 </view> <view class="music-box"> <!--该music-box主要是为了在music内容滚动的时候在超出music-box范围后可以隐藏超出部分--> <view class="music"> @祝晓晗创做的原声 @祝晓晗创做的原声 </view> </view> </view> </template> <style scoped> .list-left{ width: 70%; height: 120px; color: white; } .author { height: 35px; line-height: 35px; font-size: 17px; } .title { width: 100%; line-height: 25px; font-size: 12px; word-wrap: break-word; color: #FFFAF0; } .music-box { overflow: hidden; <!--滚动的时候超出部分隐藏--> width: 70%; } .music { width: 200%; height: 35px; line-height: 35px; font-size: 12px; animation: scroll-x 5s linear 0.2s infinite; <!--应用动画--> } @keyframes scroll-x{ <!--添加文字水平滚动动画--> 0% { transform: translate3d(80%, 0, 0); <!--80%位置出现,而后向左边滚动--> } 100% { transform: translate3d(-80%, 0, 0); <!--动画结束后到达-80%位置--> } } </style>
// components/video-list.vueapp
<template> <view class="video-list"> <view class="swiper-box"> <swiper class="swiper" :vertical="true"> <swiper-item v-for="(item,index) in videos" :key="index"> <view class="swiper-item"> <video-player :video="item" :index="index"> </video-player> </view> <view class="left-box"> <!--将左侧信息栏组件放到<swiper-item>中同视频一块儿渲染出来--> <list-left></list-left> </view> </swiper-item> </swiper> </view> </view> </template> <style> .left-box { <!--给左侧列表组件添加绝对定位 并设置z-index以显示到视频上方--> position: absolute; bottom: 50px; left: 10px; z-index: 20; } </style>
右侧图标栏组件,主要分为: 头像图标(头像设置border-radius)、 收藏图标(iconfont图标)、 评论图标(iconfont图标)、 分享图标(iconfont图标)、 音乐图标(图片设置border-radius),右侧图标栏组件设置一个固定宽度,而后让各类图标依次排列便可,如:
// components/list-right.vueide
<template> <view class="list-right"> <view class="author-img"> <img class="img" src="../static/zxh.jpg"/> </view> <view class="right-box"> <view class="icon iconfont icon-xin"></view> <view class="count">72.2w</view> </view> <view class="right-box"> <view class="icon iconfont icon-pinglun1"></view> <view class="count">1.8w</view> </view> <view class="right-box"> <view class="icon iconfont icon-arrow-"></view> <view class="count">6645</view> </view> <view class="music-img"> <img class="img" src="../static/music.jpg"/> </view> </view> </template> <style scoped> .list-right { width: 60px; } .author-img { width: 60px; text-align: center; } .img { width: 50px; height: 50px; border-radius: 50%; } .author-img img{ border: 2px solid #FFFFFF; } .right-box { margin: 20px auto; color: white; text-align: center; font-size: 12px; } .icon { font-size: 40px; } .music-img { width: 60px; height: 51px; text-align: center; margin-top: 20px; animation: around 1.5s linear 0.2s infinite; <!--使用动画--> } @keyframes around { <!--添加360环绕旋转动画--> 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } </style>
当点击头像下部的加号图标,能够对该用户进行关注,即 隐藏加号图标,还有就是 收藏爱心图标颜色切换,当点击收藏爱心图标,爱心图标变成红色,再次点击收藏爱心图标,爱心图标变回白色,这里先只处理颜色的变化,具体后台交互暂不处理。
// 在头像图标下方经过绝对定位添加一个加号图标,并定位到头像底部oop
<view class="author-img"> <img class="img" src="../static/zxh.jpg"/> <view class="follow iconfont icon-jiahao" v-show="showFollow" @click="hideFollow"><!--添加一个加号图标,以及监听hideFollow事件--> </view> </view> <view class="right-box"> <view class="icon iconfont icon-xin" :class="{fav: isFav}" @click="changeColor"></view><!--监听切换收藏爱心图标颜色--> <view class="count">72.2w</view> </view> <script> export default { data() { return { showFollow: true, isFav: false } }, methods: { hideFollow() { // 隐藏关注加号图标 this.showFollow = false; }, changeColor() { this.isFav = !this.isFav; // 切换收藏爱心颜色 } } } </script> <style scoped> .follow { color: white; position: absolute; width: 18px; height: 18px; line-height: 18px; background: red; border-radius: 50%; text-align: center; left: 23px; bottom: -5px; font-weight: bold; } .fav { color:red; } </style>
所谓滑动播放,即向上滑动的时候,暂停当前播放视频而且播放下一个视频,向下滑动的时候,暂停当前播放视频,播放上一个视频,而这最关键的就是 如何判断是向上滑动仍是向下滑动。 <swiper>组件给咱们提供了一个change事件,咱们能够监听这个change事件, 拿到滑动完成后滑动到了第几页,即<swiper-item>的序号(从0开始),而后与滑动前的当前page相比较,就能够知道是向上滑仍是向下滑了。
判断好了是上滑仍是下滑后,咱们还须要对上滑和下滑做出正确的处理,咱们须要可以拿到每一个视频播放组件,而后调用视频播放组件上的相关方法对播放进行控制,这就是涉及到了 父组件如何调用子组件上方法,父组件要想调用子组件上的方法, 关键是父组件要可以拿到子组件对象,咱们能够经过 ref实现,由于每个视频播放组件是video-list视频列表组件的一个子组件,因此咱们能够 在video-list视频列表组件中给每个video-player视频播放组件添加上一个ref="player",便可拿到对应的视频播放组件了。
// components/video-list.vue动画
<swiper class="swiper" :vertical="true" @change="slider"> <!--监听change事件--> <swiper-item v-for="(item,index) in videos" :key="index"> <view class="swiper-item"> <video-player ref="players" <!--给每个视频播放组件添加一个ref标识--> :video="item" :index="index"> </video-player> </view> </swiper> </swiper> <script> export default { data() { return { currentPage: 0 // 保存当前page的编号 } }, methods: { slider(e) { const targetPage = e.detail.current; if (targetPage === this.currentPage + 1) { console.log("向上滑动"); this.$refs.players[this.currentPage + 1].playFromHead(); // 下一个开始播放而且从头开始播放 this.$refs.players[this.currentPage].pause(); // 当前视频暂停播放 } else if(targetPage === this.currentPage - 1) { console.log("向下滑动"); this.$refs.players[this.currentPage - 1].playFromHead(); // 上一个开始播放而且从头开始播放 this.$refs.players[this.currentPage].pause(); // 当前视频暂停播放 } this.currentPage = targetPage; } } } </script>
须要注意的是, this.$refs.players返回的是一个数组,即 全部播放组件的实例,咱们经过不一样的索引便可取得对应的视频播放组件,而后进行相应的播放控制了,接下来就是要给每个视频播放组件添加上播放控制的方法,咱们 须要给<video>组件添加上一个id,而后 经过这个id能够建立出video上下文,便可调用play()、pause()、seek()等相关方法对播放进行控制。
// components/video-player.vuethis
<template> <view class="video-player"> <video class="video" id="myVideo" <!--给video组件添加一个id,以便获取到video上下文对象--> :src= "video.src" :controls="false" :loop="true"> </video> </view> </template> <script> export default { onReady() { this.videoContext = uni.createVideoContext("myVideo", this); // 获取video上下文对象 }, methods: { play() { this.videoContext.play(); }, pause() { this.videoContext.pause(); }, playFromHead() { // 跳转到开始位置并播放 this.videoContext.seek(0); this.play(); } } } </script>
要想实现单击视频播放组件,视频能够进行播放和暂停切换,那么咱们 须要给视频播放组件添加一个isPlay属性表示视频是否处于播放中,若是是播放中,那么点击就暂停,若是不是播放中,那么点击就播放,同时,因为 uni-app不支持vue的dblclick事件的,因此咱们还 须要对单击和双击操做进行判断,咱们须要定义一个变量用于记录用户点击次数,若是300ms内用户点击次数大于等于2,那么就是双击,不然就是单击,如:
<template> <view class="video-player"> <video class="video" id="myVideo" :src= "video.src" :controls="false" :loop="true" @click="doClick"><!--添加click事件进行视频播放和暂停的切换--> </video> </view> </template> <script> let timer = null; // 定义一个定时器 export default { data() { return { isPlay: false, // 当前视频是否在播放中,默认为false clickCount: 0 // 记录当前用户点击次数,默认为0 } }, methods: { play() { this.videoContext.play(); this.isPlay = true; // 进入视频播放状态设置isPlay为true }, pause() { this.videoContext.pause(); this.isPlay = false; // 进入视频暂停状态设置isPlay为false }, playFromHead() { this.videoContext.seek(0); this.play(); }, doClick() { // 进行视频播放和暂停的切换 if (timer) { clearTimeout(timer); } this.clickCount++; // 每次单击视频播放组件,点击次数加1 timer = setTimeout(() => { if (this.clickCount >=2 ) { // 若是300ms内点击次数大于等于2就表示是双击了 console.log("双击"); this.$emit("follow"); // 双击的话向video-list父组件(视频列表组件)发送一个follow事件 } else { console.log("单击"); if (this.isPlay) { this.pause(); } else { this.play(); } } this.clickCount = 0; // 重置点击次数为0 }, 300); } } } </script>
双击的时候会向video-list父组件(视频列表组件)发送一个follow事件,video-list组件监听到follow事件后再通知<list-right>组件调用其方法让其爱心图标变红便可,如:
<template> <video-player @follow="follow"> </video-player> <view class="right-box"> <list-right ref="listRight"></list-right> <!--给list-right组件添加ref标识--> </view> </template> <script> export default { follow() { this.$refs.listRight[0].follow(); } } </script>
以前咱们的视频播放组件接收了一个index属性,即当前视频对应的索引号,咱们能够经过这个索引号判断当前视频是不是第一个,而后将其video组件的autoPlay设置为true便可自动播放。
<template> <view class="video-player"> <vide :autoplay="auto> <!--绑定autoplay属性控制是否自动播放--> </video> </view> </template> <script> export default { data() { return { auto: false // 是否自动播放 } }, methods: { autoPlay() { if (this.index === 0) { this.auto = true; } } }, created() { this.autoPlay(); } } </script>
至此,首页已经完成,效果图以下: