查看: 2062|回复: 0
打印 上一主题 下一主题

Vue3+Swipe仿抖音短视频/微信直播实例

[复制链接]

该用户从未签到

28

主题

33

帖子

163

积分

注册会员

Rank: 2

积分
163
QQ
跳转到指定楼层
楼主
发表于 2021-2-4 22:31:32 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
介绍
vue3Douyin 是一款基于vite2构建工具搭建开发的vue3仿制抖音实战项目。使用了vue3.0+vuex+vant3+v3popup等技术编码开发,实现小视频上下滑动切换、点赞/评论/分享等功能。


小视频页有附近/关注/推荐三大模块,可以实现左右及上下滑动切换效果。



如上图:这个是原型设计,最终效果是下面这些展示图片。











实现技术
  • 构建工具:Vite.js
  • 编辑器:Vscode
  • MVVM框架:Vue^3.0.5
  • 状态管理:Vuex^4.0.0-rc.2
  • 页面路由:Vue-Router^4.0.3
  • UI组件库:Vant^3.0.4 (有赞手机端vue3组件库)
  • 弹框组件:v3popup(基于vue3自定义手机端弹出层组件)
  • 字体图标:阿里iconfont图标
  • 顶部条+底部栏:基于vue3自定义navbar/tabbar组件















项目结构目录


vue3实现短视频/直播效果
小视频/直播模板整体布局分为顶部Navbar、视频信息区、底部Toolbar三个模块。








  1. <template>
  2.     <div class="bg-161823">
  3.         <!-- >>顶部NavBar -->
  4.         <navbar :back="false" bgcolor="transparent" transparent>
  5.             <template v-slot:title>
  6.                 ...
  7.             </template>
  8.             <template v-slot:right><div><i class="iconfont icon-search"></i></div></template>
  9.         </navbar>

  10.         <!-- >>主面板 -->
  11.         <div class="vui__scrollview flex1">
  12.             <div class="vui__swipeview">
  13.                 <!-- ///滑动切换区 -->
  14.                 <van-swipe ref="swipeHorizontalRef" :show-indicators="false" :loop="false" @change="handleSwipeHorizontal">
  15.                     <van-swipe-item v-for="(item,index) in videoLs" :key="index">
  16.                         <template v-if="item.category == 'nearby'">
  17.                             <div class="swipe__nearLs">
  18.                                 ...
  19.                             </div>
  20.                         </template>
  21.                         <template v-if="item.category == 'recommend' || item.category == 'follow'">
  22.                             <van-swipe vertical lazy-render :show-indicators="false" :loop="false" @change="handleSwipeVertical">
  23.                                 <van-swipe-item v-for="(item2, index2) in item.list" :key="index2">
  24.                                     <!-- ///视频模块 -->
  25.                                     <div class="swipe__video">
  26.                                         <video class="vdplayer" :id="'vd-'+index+'-'+index2" loop preload="auto"
  27.                                             :src="item2.src"
  28.                                             :poster="item2.poster"
  29.                                             webkit-playsinline="true"
  30.                                             x5-video-player-type="h5-page"
  31.                                             x5-video-player-fullscreen="true"
  32.                                             playsinline
  33.                                             @click="handleVideoClicked"
  34.                                         >
  35.                                         </video>
  36.                                         <span v-show="!isPlay" class="btn__play" @click="handleVideoClicked"><i class="iconfont icon-bofang"></i></span>
  37.                                     </div>
  38.                                     <!-- ///信息模块 -->
  39.                                     <div class="swipe__vdinfo flexbox flex-col">
  40.                                         <div class="flexbox flex-alignb">
  41.                                             <!-- ///底部信息栏 -->
  42.                                             <div class="swipe__footbar flex1">
  43. ...
  44.                                             </div>
  45.                                             <!-- ///右侧工具栏 -->
  46.                                             <div class="swipe__toolbar">
  47.                                                 ...
  48.                                             </div>
  49.                                         </div>
  50.                                     </div>
  51.                                 </van-swipe-item>
  52.                             </van-swipe>
  53.                         </template>
  54.                     </van-swipe-item>
  55.                 </van-swipe>
  56.                 <!-- ///底部进度条 -->
  57.                 <div class="swipe__progress"><i class="bar" :style="{'width': vdProgress+'%'}"></i></div>
  58.             </div>
  59.         </div>

  60.         <!-- >>底部TabBar -->
  61.         <tabbar
  62.             bgcolor="linear-gradient(to bottom, transparent, rgba(0,0,0,.6))"
  63.             color="rgba(255,255,255,.6)"
  64.             activeColor="#fff"
  65.             fixed
  66.         />

  67.         <!-- …… -->

  68.     </div>
  69. </template>

  70. <script>
  71. /**
  72. * @Desc    Vue3.0实现小视频功能
  73. * @Time    andy by 2021-02
  74. * @About   Q:282310962  wx:xy190310
  75. */
  76. import { onMounted, onUnmounted, ref, reactive, toRefs, inject, nextTick } from 'vue'

  77. ...

  78. export default {
  79.     components: {
  80.         CmtEditor,
  81.     },
  82.     setup() {
  83.         // 定时器
  84.         const vdTimer = ref(null)
  85.         const tapTimer = ref(null)
  86.         const swipeHorizontalRef = ref(null)

  87.         const editorRef = ref(null)

  88.         const v3popup = inject('v3popup')

  89.         const data = reactive({
  90.             // ...
  91.         })

  92.         onMounted(() => {
  93.             swipeHorizontalRef.value.swipeTo(data.activeNav, {immediate: true})

  94.             // ...
  95.         })

  96.         // ...

  97.         // 垂直切换页面事件
  98.         const handleSwipeVertical = (index) => {
  99.             if(data.activeNav == 0) {
  100.                 // 附近页
  101.                 data.activeOneIdx = index
  102.             }else if(data.activeNav == 1) {
  103.                 // 关注页
  104.                 data.activeTwoIdx = index
  105.             }else if(data.activeNav == 2) {
  106.                 // 推荐页
  107.                 data.activeThreeIdx = index
  108.             }

  109.             vdTimer.value && clearInterval(vdTimer.value)
  110.             data.vdProgress = 0
  111.             data.isPlay = false
  112.             let video = getVideoContext()
  113.             if(!video) return
  114.             video.pause()
  115.             // 重新开始
  116.             video.currentTime = 0

  117.             data.activeSwipeIndex = index

  118.             // 自动播放下一个
  119.             handlePlay()
  120.         }

  121.         // 播放
  122.         const handlePlay = () => {
  123.             let video = getVideoContext()
  124.             if(!video) return
  125.             video.play()
  126.             data.isPlay = true

  127.             // 设置进度条
  128.             vdTimer.value = setInterval(() => {
  129.                 handleProgress()
  130.             }, 16)
  131.         }

  132.         // 暂停
  133.         const handlePause = () => {
  134.             let video = getVideoContext()
  135.             if(!video) return
  136.             video.pause()
  137.             data.isPlay = false
  138.             vdTimer.value && clearInterval(vdTimer.value)
  139.         }

  140.         // 视频点击事件(判断单/双击)
  141.         const handleVideoClicked = () => {
  142.             tapTimer.value && clearTimeout(tapTimer.value)
  143.             data.clickNum++
  144.             tapTimer.value = setTimeout(() => {
  145.                 if(data.clickNum >= 2) {
  146.                     console.log('双击事件')
  147.                 }else {
  148.                     console.log('单击事件')
  149.                     if(data.isPlay) {
  150.                         handlePause()
  151.                     }else {
  152.                         handlePlay()
  153.                     }
  154.                 }
  155.                 data.clickNum = 0
  156.             }, 300)
  157.         }

  158.         // 播放进度条
  159.         const handleProgress = () => {
  160.             let video = getVideoContext()
  161.             if(!video) return
  162.             let curTime = video.currentTime.toFixed(1)
  163.             let duration = video.duration.toFixed(1)
  164.             data.vdProgress = parseInt((curTime / duration).toFixed(2) * 100)
  165.         }

  166.         // ...

  167.         return {
  168.             ...toRefs(data),

  169.             // ...
  170.         }
  171.     }
  172. }
  173. </script>
复制代码










另外项目中所有的弹窗功能,均是vue3自定义移动端弹框v3popup组件来实现。

vue3系列:vue3.0自定义弹框组件V3Popup|vue3.x手机端弹框组件


Ending,运用vue3+vant3开发仿抖音小视频/直播实战就分享到这里。希望大家喜欢哈!

040360截图20210201113501849.png (269.39 KB, 下载次数: 98)

040360截图20210201113501849.png
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 分享淘帖
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Swiper中文网 ( 粤ICP备15001020号

GMT+8, 2024-4-19 14:12 , Processed in 0.074198 second(s), 31 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表