基于vue+uniapp直播项目实现uni-app仿抖音/陌陌直播室功能


Posted in Javascript onNovember 12, 2019

一、项目简介

uni-liveShow是一个基于vue+uni-app技术开发的集小视频/IM聊天/直播等功能于一体的微直播项目。界面仿制抖音|火山小视频/陌陌直播,支持编译到多端(H5、小程序、App端) 且兼容效果一致。

二、效果预览

在H5、小程序、App端测试效果如下:(后续大图均为APP端)

基于vue+uniapp直播项目实现uni-app仿抖音/陌陌直播室功能

三、使用技术

  • 编码器+技术:HBuilderX + vue/NVue/uniapp/vuex
  • iconfont图标:阿里字体图标库
  • 自定义导航栏 + 底部Tabbar
  • 弹窗组件:uniPop(uni-app封装自定义弹出窗)
  • 测试环境:H5端 + 小程序 + App端

基于vue+uniapp直播项目实现uni-app仿抖音/陌陌直播室功能

基于vue+uniapp直播项目实现uni-app仿抖音/陌陌直播室功能

基于vue+uniapp直播项目实现uni-app仿抖音/陌陌直播室功能

基于vue+uniapp直播项目实现uni-app仿抖音/陌陌直播室功能

基于vue+uniapp直播项目实现uni-app仿抖音/陌陌直播室功能

基于vue+uniapp直播项目实现uni-app仿抖音/陌陌直播室功能

基于vue+uniapp直播项目实现uni-app仿抖音/陌陌直播室功能

基于vue+uniapp直播项目实现uni-app仿抖音/陌陌直播室功能

基于vue+uniapp直播项目实现uni-app仿抖音/陌陌直播室功能

基于vue+uniapp直播项目实现uni-app仿抖音/陌陌直播室功能

基于vue+uniapp直播项目实现uni-app仿抖音/陌陌直播室功能

基于vue+uniapp直播项目实现uni-app仿抖音/陌陌直播室功能

基于vue+uniapp直播项目实现uni-app仿抖音/陌陌直播室功能

基于vue+uniapp直播项目实现uni-app仿抖音/陌陌直播室功能

基于vue+uniapp直播项目实现uni-app仿抖音/陌陌直播室功能

基于vue+uniapp直播项目实现uni-app仿抖音/陌陌直播室功能

基于vue+uniapp直播项目实现uni-app仿抖音/陌陌直播室功能

基于vue+uniapp直播项目实现uni-app仿抖音/陌陌直播室功能

◆ uniapp计算设备顶部状态栏高度

/**
 * @desc uniapp主页面App.vue
 * @about Q:282310962 wx:xy190310
 */

<script>
 import Vue from 'vue'
 export default {
 onLaunch: function() {
 // console.log('App Launch')
 uni.getSystemInfo({
 success:function(e){
 Vue.prototype.statusBar = e.statusBarHeight
 // #ifndef MP
 if(e.platform == 'android') {
 Vue.prototype.customBar = e.statusBarHeight + 50
 }else {
 Vue.prototype.customBar = e.statusBarHeight + 45
 }
 // #endif
 
 // #ifdef MP-WEIXIN
 let custom = wx.getMenuButtonBoundingClientRect()
 Vue.prototype.customBar = custom.bottom + custom.top - e.statusBarHeight
 // #endif
 
 // #ifdef MP-ALIPAY
 Vue.prototype.customBar = e.statusBarHeight + e.titleBarHeight
 // #endif
 }
 })
 },
 }
</script>

◆ 项目中顶部透明导航栏设置

顶部导航栏采用的是自定义模式,可设置透明背景(如:个人主页/朋友圈动态) 具体可参看这篇文章:https://3water.com/article/174034.htm

基于vue+uniapp直播项目实现uni-app仿抖音/陌陌直播室功能基于vue+uniapp直播项目实现uni-app仿抖音/陌陌直播室功能

<header-bar :isBack="true" title=" " :bgColor="{background: 'transparent'}" transparent>
 <text slot="back" class="uni_btnIco iconfont icon-guanbi" style="font-size: 25px;"></text>
 <text slot="iconfont" class="uni_btnIco iconfont icon-dots mr_5" style="font-size: 25px;"></text>
</header-bar>

◆ uniapp仿抖音小视频效果

项目中小视频界面功能效果类似抖音/火山小视频,使用swiper组件实现上下滑动切换视频播放。

基于vue+uniapp直播项目实现uni-app仿抖音/陌陌直播室功能

<swiper :indicator-dots="false" :duration="200" :vertical="true" :current="videoIndex" @change="handleSlider" style="height: 100%;">
 <block v-for="(item,index) in vlist" :key="index">
 <swiper-item>
 <view class="uni_vdplayer">
 <video :id="'myVideo' + index" :ref="'myVideo' + index" class="player-video" :src="item.src" 
 :controls="false" :loop="true" :show-center-play-btn="false" objectFit="fill">
 </video>
 <!-- 中间播放按钮 -->
 <view class="vd-cover flexbox" @click="handleClicked(index)"><text v-if="!isPlay" class="iconfont icon-bofang"></text></view>
 <!-- 底部信息 -->
 <view class="vd-footToolbar flexbox flex_alignb">
 <view class="vd-info flex1">
 <view class="item at">
 <view class="kw" v-for="(kwItem,kwIndex) in item.keyword" :key="kwIndex"><text class="bold fs_18 mr_5">#</text> {{kwItem}}</view>
 </view>
 <view class="item subtext">{{item.subtitle}}</view>
 <view class="item uinfo flexbox flex_alignc">
 <image class="avator" :src="item.avator" mode="aspectFill" /><text class="name">{{item.author}}</text> <text class="btn-attention bg_linear1" :class="item.attention ? 'on' : ''" @tap="handleAttention(index)">{{item.attention ? '已关注' : '关注'}}</text>
 </view>
 <view class="item reply" @tap="handleVideoComment"><text class="iconfont icon-pinglun mr_5"></text> 写评论...</view>
 </view>
 <view class="vd-sidebar">
 <view v-if="item.cart" class="ls cart flexbox bg_linear3" @tap="handleVideoCart(index)"><text class="iconfont icon-cart"></text></view>
 <view class="ls" @tap="handleIsLike(index)"><text class="iconfont icon-like" :class="item.islike ? 'like' : ''"></text><text class="num">{{ item.likeNum+(item.islike ? 1: 0) }}</text></view>
 <view class="ls" @tap="handleVideoComment"><text class="iconfont icon-liuyan"></text><text class="num">{{item.replyNum}}</text></view>
 <view class="ls"><text class="iconfont icon-share"></text><text class="num">{{item.shareNum}}</text></view>
 </view>
 </view>
 </view>
 </swiper-item>
 </block>
</swiper>

视频滑动切换 播放、暂停 及单击/双击判断,商品及评论展示

<script>
 // 引入商品广告、评论
 import videoCart from '@/components/cp-video/cart.vue'
 import videoComment from '@/components/cp-video/comment'
 
 let timer = null
 export default {
 data() {
 return {
 videoIndex: 0,
 vlist: videoJson,
 
 isPlay: true, //当前视频是否播放中
 clickNum: 0, //记录点击次数
 }
 },
 components: {
 videoCart, videoComment
 },
 onLoad(option) {
 this.videoIndex = parseInt(option.index)
 },
 onReady() {
 this.init()
 },
 methods: {
 init() {
 this.videoContextList = []
 for(var i = 0; i < this.vlist.length; i++) {
 // this.videoContextList.push(this.$refs['myVideo' + i][0])
 this.videoContextList.push(uni.createVideoContext('myVideo' + i, this));
 }
 
 setTimeout(() => {
 this.play(this.videoIndex)
 }, 200)
 },
 
 // 滑动切换
 handleSlider(e) {
 let curIndex = e.detail.current
 if(this.videoIndex >= 0){
 this.videoContextList[this.videoIndex].pause()
 this.videoContextList[this.videoIndex].seek(0)
 this.isPlay = false
 }
 if(curIndex === this.videoIndex + 1) {
 this.videoContextList[this.videoIndex + 1].play()
 this.isPlay = true
 }else if(curIndex === this.videoIndex - 1) {
 this.videoContextList[this.videoIndex - 1].play()
 this.isPlay = true
 }
 this.videoIndex = curIndex
 },
 // 播放
 play(index) {
 this.videoContextList[index].play()
 this.isPlay = true
 },
 // 暂停
 pause(index) {
 this.videoContextList[index].pause()
 this.isPlay = false
 },
 // 点击视频事件
 handleClicked(index) {
 if(timer){
 clearTimeout(timer)
 }
 this.clickNum++
 timer = setTimeout(() => {
 if(this.clickNum >= 2){
 console.log('双击视频')
 }else{
 console.log('单击视频')
 if(this.isPlay){
 this.pause(index)
 }else{
 this.play(index)
 }
 }
 this.clickNum = 0
 }, 300)
 },
 
 
 // 喜欢
 handleIsLike(index){
 let vlist = this.vlist
 vlist[index].islike =! vlist[index].islike
 this.vlist = vlist
 },
 // 显示评论
 handleVideoComment() {
 this.$refs.videoComment.show()
 },
 
 // 显示购物车
 handleVideoCart(index) {
 this.$refs.videoCart.show(index)
 },
 }
 }
</script>

在项目开发过程中,遇到了视频video层级高不能覆盖的问题,使用nvue页面就可以解决view覆盖在video之上。.nvue(native vue的缩写)

更多关于nvue页面开发,可以参看:uniapp开发nvue页面

◆ uniapp聊天页面实现

项目中的聊天页面,功能效果这里就不详细介绍了,可参看这篇:uni-app聊天室|vue+uniapp仿微信聊天实例

◆ 直播页面live.nvue

为避免video不能覆盖问题,直播页面采用的是nvue编写,开发过程也遇到了一些坑,尤其是css,全部是flex布局,而且不能多级嵌套,有些css属性不支持。

基于vue+uniapp直播项目实现uni-app仿抖音/陌陌直播室功能

<template>
 <div class="nlv__container">
 <view class="nlv_main">
 <swiper class="nlv-swiper" :indicator-dots="false" :vertical="false" :current="videoIndex" @change="handleSlider">
 <swiper-item v-for="(item, index) in vlist" :key="index">
 <!-- //直播区 -->
 <view class="nlv-playerbox">
 <video :id="'myVideo' + index" :ref="'myVideo' + index" class="player-video" :src="item.src" :autoplay="index == videoIndex"
 :controls="false" :loop="true" :show-center-play-btn="false" objectFit="fill" :style="{height: winHeight, width: winWidth}">
 </video>
 
 <!-- //顶部 -->
 <view class="nlv_topbar" :style="{ height: headerBarH, 'padding-top': statusBarH }">
 ...
 </view>
 
 <!-- //排名信息 -->
 <view class="nlv-rankbox" :style="{top: headerBarH}">
 <view class="nlv-rkls">
 <text class="rkitem">总排名{{item.allRank}}</text>
 <text v-if="item.hourRank" class="rkitem">小时榜第{{item.hourRank}}名</text>
 </view>
 <text class="nlv-uid">U直播:{{item.uid}}</text>
 </view>
 
 <!-- //底部信息栏 -->
 <view class="nlv-footToolbar">
 <!-- 送礼物提示 -->
 <view class="nlv-giftTipPanel">
 ...
 </view>
 
 <!-- 滚动msg信息 -->
 <scroll-view class="nlv-rollMsgPanel" scroll-y show-scrollbar="false">
 <block v-for="(msgitem, msgidx) in item.rollmsg" :key="msgidx">
  <view class="nlv-msglist"><view class="msg_bg"><text class="msg_name">{{msgitem.uname}}</text> <text class="msg_text">{{msgitem.content}}</text></view></view>
 </block>
 </scroll-view>
 
 <view class="nlv-infobox">
 <view class="nlv_reply" @tap="handleRollMsg(index)"><text class="nlv_reply_text">说点什么...</text></view>
 <view class="nlv_btntool">
  ...
  <view v-if="item.cart" class="btn-toolitem" @tap="handleLiveCart(index)"><text class="iconfont i-btntool" style="color: #ff4e0e;font-size: 20px;"></text></view>
  <view class="btn-toolitem btn-toolitem-cart" @tap="handleLiveGift"><text class="iconfont i-btntool"></text></view>
  ...
 </view>
 </view>
 </view>
 </view>
 </swiper-item>
 </swiper>
 </view>
 
 <!-- 商品广告、滚动消息、礼物 -->
 <live-cart ref="liveCart" :vlist="vlist" />
 <roll-msg ref="rollMsg" :vlist="vlist" />
 <live-gift ref="liveGift" />
 </div>
</template>

另外引入阿里字体图标也需注意:通过weex方式引入

beforeCreate() {
 // 引入iconfont字体
 // #ifdef APP-PLUS
 const domModule = weex.requireModule('dom')
 domModule.addRule('fontFace', {
 fontFamily: "nvueIcon",
 'src': "url('../../../static/fonts/iconfont.ttf')"
 });
 // #endif
},

至于视频滑动切换和上面小视频操作差不多,就不贴码了。到这里,uni-liveShow项目基本介绍完了,希望对大家有些许帮助。?

最后,附上两个vue/react项目案例:

vue+vuex+vue-router仿微信网页版聊天室https://3water.com/article/160487.htm

angular+ng-router手机端聊天IM实战开发https://3water.com/article/71356.htm

总结

以上所述是小编给大家介绍的基于vue+uniapp直播项目实现uni-app仿抖音/陌陌直播室功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Javascript 相关文章推荐
常用简易JavaScript函数
Apr 09 Javascript
javascript dom代码应用 简单的相册[firefox only]
Jun 12 Javascript
基于node.js的快速开发透明代理
Dec 25 Javascript
对 jQuery 中 data 方法的误解分析
Jun 18 Javascript
Javascript核心读书有感之类型、值和变量
Feb 11 Javascript
js实现touch移动触屏滑动事件
Apr 17 Javascript
javascript html5实现表单验证
Mar 01 Javascript
Jquery获取当前城市的天气信息
Aug 05 Javascript
Vue结合原生js实现自定义组件自动生成示例
Jan 21 Javascript
jQuery实现的弹幕效果完整实例
Sep 06 jQuery
javascript json字符串到json对象转义问题
Jan 22 Javascript
Vue 中 filter 与 computed 的区别与用法解析
Nov 21 Javascript
vuex管理状态 刷新页面保持不被清空的解决方案
Nov 11 #Javascript
vuex实现数据状态持久化
Nov 11 #Javascript
vue 更改连接后台的api示例
Nov 11 #Javascript
vue路由守卫,限制前端页面访问权限的例子
Nov 11 #Javascript
vue在路由中验证token是否存在的简单实现
Nov 11 #Javascript
vuex存储token示例
Nov 11 #Javascript
Vuex实现数据增加和删除功能
Nov 11 #Javascript
You might like
一个程序下载的管理程序(一)
2006/10/09 PHP
PHPCMS2008广告模板SQL注入漏洞修复
2016/10/11 PHP
利用Dojo和JSON建立无限级AJAX动态加载的功能模块树
2007/03/24 Javascript
在jQuery中 常用的选择器介绍
2013/04/16 Javascript
jQuery操作input值的各种方法总结
2013/11/21 Javascript
用于deeplink的js方法(判断手机是否安装app)
2014/04/02 Javascript
jQuery操作JSON的CRUD用法实例
2015/02/25 Javascript
js获取微信版本号的方法
2015/05/12 Javascript
JS中常用的正则表达式
2016/09/29 Javascript
详细讲解JavaScript中的this绑定
2016/10/10 Javascript
Vuejs 2.0 子组件访问/调用父组件的方法(示例代码)
2018/02/08 Javascript
JS从非数组对象转数组的方法小结
2018/03/26 Javascript
简述vue路由打开一个新的窗口的方法
2018/11/29 Javascript
150行Node.js实现的dns代理工具
2019/08/02 Javascript
[41:21]夜魇凡尔赛茶话会 第三期02:看图识人
2021/03/11 DOTA
详解Python中的__init__和__new__
2014/03/12 Python
python结合shell查询google关键词排名的实现代码
2016/02/27 Python
Python常见数据类型转换操作示例
2019/05/08 Python
解决python -m pip install --upgrade pip 升级不成功问题
2020/03/05 Python
Python opencv相机标定实现原理及步骤详解
2020/04/09 Python
使用jupyter notebook将文件保存为Markdown,HTML等文件格式
2020/04/14 Python
matplotlib jupyter notebook 图像可视化 plt show操作
2020/04/24 Python
创造美妙香氛体验:Aera扩散器和香水
2018/11/25 全球购物
美国室内盆栽植物购买网站:Plants.com
2020/04/24 全球购物
Java语言程序设计测试题选择题部分
2014/04/03 面试题
金融专业推荐信
2013/11/14 职场文书
监察建议书范文
2014/03/12 职场文书
同学聚会主持词
2014/03/18 职场文书
房屋租赁协议书
2014/04/10 职场文书
优秀电子工程系毕业生求职信
2014/05/24 职场文书
2014年客服工作总结与计划
2014/12/09 职场文书
个人求职自荐信范文
2015/03/06 职场文书
团委副书记工作总结
2015/08/14 职场文书
电工实训心得体会
2016/01/14 职场文书
mysql 8.0.24 安装配置方法图文教程
2021/05/12 MySQL
Python中常见的反爬机制及其破解方法总结
2021/06/10 Python