uniapp+nvue仿抖音效果|小视频直播室

2019年11月14日 307点热度 0人点赞 0条评论

图片


项目介绍:

今天给大家分享的一个项目是基于uniapp+vue+nvue技术开发的仿抖音小视频|陌陌直播项目,界面效果类似抖音,可实现上下滑动切换小视频播放,还有点赞、评论及商品广告等功能,支持编译到H5、小程序、App端。


效果预览:

分别是在H5端、小程序、App端及真机下效果,后续均展示App效果图

图片


技术实现:

  • 编辑器/技术:HBuilderX + vue/NVue/uniapp/vuex

  • 字体图标:阿里iconfont字体图标库

  • 自定义导航栏 + 底部Tabbar

  • 弹窗组件:uniPop(uni-app封装自定义Modal弹窗)

  • 测试环境:H5端/小程序/App端/真机


图片

图片

图片

图片

图片

图片

图片

图片

图片

图片

图片

图片

图片

图片

图片

图片

图片

图片

图片

图片

图片

自定义导航模式:App.vue获取顶部状态栏高度

<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>

Nvue页面中引入阿里字体图标,和vue页面不一样,不能单单使用<text class="iconfont icon-search"></text>这种方式引入,会在手机无法显示图标,需要通过Unicode字符方式

调用方式:<text class="nvueIcon">&#xe600;</text>

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

main.js引入公共组件及样式库

import Vue from 'vue'import App from './App'
import './static/fonts/iconfont.css'import './assets/css/reset.css'import './assets/css/layout.css'
// 状态管理import store from './store'Vue.prototype.$store = store
// 公共组件import headerBar from './components/header/header.vue'import tabBar from './components/tabbar/tabbar.vue'import popupWindow from './components/popupWindow.vue'Vue.component('header-bar', headerBar)Vue.component('tab-bar', tabBar)Vue.component('popup-window', popupWindow)
// 自定义弹窗组件import uniPop from './components/uniPop/uniPop.vue'Vue.component('uni-pop', uniPop)
Vue.config.productionTip = falseApp.mpType = 'app'
const app = new Vue({ ...App})app.$mount()

另外消息模块聊天功能,可参考之前这篇文章:

uni-app聊天App实例|vue+uniapp仿微信界面|红包|朋友圈

uniapp+swiper组件实现抖音上下滑动切换效果,可点击播放、暂停。

图片

<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>    const videoJson = require('./mock-video.js')        // 引入商品广告、评论    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            },                                    // 喜欢            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层级过高,view组件不能覆盖其上,可以使用cover-view,不过该组件不能内嵌其他组件,故可采用nvue页面模式,nvue和vue页面结构基本一致,不过编写需要注意css样式,不能使用多个css选择器,只能单个定义。

图片

34750uniapp+nvue仿抖音效果|小视频直播室

这个人很懒,什么都没留下

文章评论