基于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 相关文章推荐
基于jQuery的message插件实现右下角弹出消息框
Jan 11 Javascript
JavaScript检查弹出窗口是否被阻拦的方法技巧
Mar 13 Javascript
JavaScript File API实现文件上传预览
Feb 02 Javascript
JavaScript中实现无缝滚动、分享到侧边栏实例代码
Apr 06 Javascript
深入浅析JavaScript中with语句的理解
May 12 Javascript
js删除局部变量的实现方法
Jun 25 Javascript
JavaScript中for循环的几种写法与效率总结
Feb 03 Javascript
JS跳转手机站url的若干注意事项
Oct 18 Javascript
浅谈在vue中用webpack打包之后运行文件的问题以及相关配置方法
Feb 21 Javascript
微信小程序--获取用户地理位置名称(无须用户授权)的方法
Apr 29 Javascript
微信小程序实现转盘抽奖
Sep 21 Javascript
前端canvas中物体边框和控制点的实现示例
Aug 05 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
PHP检测字符串是否为UTF8编码的常用方法
2014/11/21 PHP
jQuery 位置插件
2008/12/25 Javascript
Javascript 计算字符串在localStorage中所占字节数
2015/10/21 Javascript
Bootstrap每天必学之折叠
2016/04/12 Javascript
html、css和jquery相结合实现简单的进度条效果实例代码
2016/10/24 Javascript
简单实现jQuery多选框功能
2017/01/09 Javascript
JS实现获取图片大小和预览的方法完整实例【兼容IE和其它浏览器】
2017/04/24 Javascript
关于JavaScript中的this指向问题总结篇
2017/07/23 Javascript
jQueryUI Sortable 应用Demo(分享)
2017/09/07 jQuery
实例详解BootStrap的动态模态框及静态模态框
2018/08/13 Javascript
vue组件之间通信实例总结(点赞功能)
2018/12/05 Javascript
Vue 组件注册实例详解
2019/02/23 Javascript
详解小程序毫秒级倒计时(适用于拼团秒杀功能)
2019/05/05 Javascript
layui实现数据表格点击搜索功能
2020/03/26 Javascript
vue中组件通信的八种方式(值得收藏!)
2019/08/09 Javascript
vue的keep-alive用法技巧
2019/08/15 Javascript
如何使用webpack打包一个库library的方法步骤
2019/12/18 Javascript
javascript实现的图片预览和上传功能示例【兼容IE 9】
2020/05/01 Javascript
jQuery实现电梯导航模块
2020/12/22 jQuery
python 算法 排序实现快速排序
2012/06/05 Python
Python3基础之条件与循环控制实例解析
2014/08/13 Python
利用Python2下载单张图片与爬取网页图片实例代码
2017/12/25 Python
pycharm安装和首次使用教程
2018/08/27 Python
pytorch 使用单个GPU与多个GPU进行训练与测试的方法
2019/08/19 Python
在 Python 中接管键盘中断信号的实现方法
2020/02/04 Python
Python连接Oracle之环境配置、实例代码及报错解决方法详解
2020/02/11 Python
优质美利奴羊毛袜,不只是徒步旅行:Darn Tough Vermont
2018/11/05 全球购物
瑞士首家网上药店折扣店:McDrogerie
2020/12/22 全球购物
Linux操作面试题
2012/05/16 面试题
应聘编辑职位自荐信范文
2014/01/05 职场文书
暖通工程师岗位职责
2014/06/12 职场文书
防汛通知
2015/04/25 职场文书
智慧人生:永远不需要向任何人解释你自己
2019/08/20 职场文书
SpringBoot整合MongoDB的实现步骤
2021/06/23 MongoDB
分析ZooKeeper分布式锁的实现
2021/06/30 Java/Android
一篇文章告诉你如何实现Vue前端分页和后端分页
2022/02/18 Vue.js