基于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实现画板的代码
Sep 05 Javascript
文档对象模型DOM通俗讲解
Nov 01 Javascript
angularJS 中$attrs方法使用指南
Feb 09 Javascript
javascript中Math.random()使用详解
Apr 15 Javascript
JS基于面向对象实现的放烟花效果
May 07 Javascript
ANGULARJS中使用JQUERY分页控件
Sep 16 Javascript
jQuery实现宽屏图片轮播实例教程
Nov 24 Javascript
js简单设置与使用cookie的方法
Jan 22 Javascript
js控制li的隐藏和显示实例代码
Oct 15 Javascript
bootstrap suggest下拉框使用详解
Apr 10 Javascript
javascript ES6 新增了let命令使用介绍
Jul 07 Javascript
微信小程序引入模块中wxml、wxss、js的方法示例
Aug 09 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
ie6 动态缩略图不显示的原因
2009/06/21 PHP
phpmyadmin 3.4 空密码登录的实现方法
2010/05/29 PHP
探讨如何使用SimpleXML函数来加载和解析XML文档
2013/06/07 PHP
PHP实现生成模糊图片的方法示例
2017/12/21 PHP
BOOM vs RR BO5 第二场 2.14
2021/03/10 DOTA
推荐dojo学习笔记
2007/03/24 Javascript
js function使用心得
2010/05/10 Javascript
基于Jquery的简单图片切换效果
2011/01/06 Javascript
jquery ajax 局部刷新小案例
2014/02/08 Javascript
javascript 实现map集合
2015/04/03 Javascript
jquery实现很酷的网页顶部图标下拉菜单效果
2015/08/22 Javascript
Javascript之Math对象详解
2016/06/07 Javascript
phantomjs导出html到pdf的方法总结
2017/10/19 Javascript
微信小程序实现鼠标拖动效果示例
2017/12/01 Javascript
Phaser.js实现简单的跑酷游戏附源码下载
2018/10/26 Javascript
angular使用md5,CryptoJS des加密的方法
2019/06/03 Javascript
[46:27]DOTA2上海特级锦标赛主赛事日 - 1 胜者组第一轮#2LGD VS MVP.Phx第一局
2016/03/02 DOTA
[09:47]2018DOTA2亚洲邀请赛4.5SOLO赛 No[o]ne vs Sumail
2018/04/06 DOTA
python的id()函数解密过程
2012/12/25 Python
Python编程之属性和方法实例详解
2015/05/19 Python
Python 将RGB图像转换为Pytho灰度图像的实例
2017/11/14 Python
微信跳一跳python辅助软件思路及图像识别源码解析
2018/01/04 Python
Python实现的微信好友数据分析功能示例
2018/06/21 Python
python保存数据到本地文件的方法
2018/06/23 Python
python计算二维矩形IOU实例
2020/01/18 Python
python实现吃苹果小游戏
2020/03/21 Python
django 连接数据库出现1045错误的解决方式
2020/05/14 Python
Django admin组件的使用
2020/10/24 Python
Python从MySQL数据库中面抽取试题,生成试卷
2021/01/14 Python
Html5新增标签与样式及让元素水平垂直居中
2019/07/11 HTML / CSS
video.js支持m3u8格式直播的实现示例
2020/05/20 HTML / CSS
意大利体育用品和运动服网上商店:Maxi Sport
2019/09/14 全球购物
大学毕业感言50字
2014/02/07 职场文书
质量月活动策划方案
2014/03/10 职场文书
教师党员自我剖析材料
2014/09/29 职场文书
WinServer2012搭建DNS服务器的方法步骤
2022/06/10 Servers