<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      uniapp-welive仿微信/抖音直播帶貨|uni-app+vue3+pinia短視頻直播商城

      基于uniapp+vue3+uv-ui跨端H5+小程序+App短視頻+直播帶貨商城Uniapp-WeLive

      uni-welive一款全新基于uniapp+vue3+pinia+vk-uview等技術跨端仿制抖音/微信直播帶貨商城項目。支持沉浸式全屏上下滑動短視頻直播,Nvue多視頻層級覆蓋,支持編譯到兼容H5+小程序+App端

      預覽效果

      編譯H5+小程序+App端效果如下

      使用技術

      • 編輯器:HbuilderX 3.98
      • 框架技術:Uniapp+Vue3+Vite4+Nvue+Pinia
      • UI組件庫:uv-ui+vk-uview
      • 彈框組件:uaPopup(uniapp封裝多端彈框組件)
      • 自定義組件:uaNavbar+uaTabbar組件
      • 本地緩存:pinia-plugin-unistorage
      • 編譯支持:H5+小程序+APP端

      大家如果對uniapp+vue3搭建跨端項目感興趣,可以去看看之前的分享文章。

      http://www.rzrgm.cn/xiaoyan2017/p/17487018.html

      uniapp-welive擁有絲滑般滑動體驗,全屏沉浸式tabbar切換,微型迷你播放時間進度條等功能。

      項目結構目錄

      目前uniapp-dylive項目,已經同步到我的原創作品集,有需要的可以去看看。

      uni-app+vue3+vk-uview跨三端仿抖音app短視頻+直播實例

      uniapp跨端自定義navbar+tabbar組件

      在components目錄下自定義navbar、tabbar組件。

      之前有過一篇分享文章,感興趣的話也可以去看看,這里就不詳細的介紹實現過程了。

      http://www.rzrgm.cn/xiaoyan2017/p/14978408.html

      uniapp+vue3小視頻模塊

      uni-welive項目短視頻模塊采用全屏沉浸式上下無縫銜接滑動效果。整體分為頂部固定tabs+視頻區+底部視頻信息浮層三大模塊。

      <ua-layout>
          <view class="ua__swipervideo flex1">
              <swiper
                  class="ua__swipervideo-wrap flex1"
                  :current="currentVideo"
                  vertical
                  :circular="true"
                  :duration="200"
                  @change="handleChange"
                  @transition="handleTransition"
              >
                  <swiper-item v-for="(item, index) in videoList" :key="index">
                      <video
                          class="ua__swipervideo-player flex1"
                          :id="'uplayer' + index"
                          :src="item.src"
                          :danmu-list="item.danmu"
                          :enable-danmu="true"
                          :controls="false"
                          :loop="true"
                          :autoplay="index == currentVideo"
                          :show-center-play-btn="false"
                          object-fit="contain"
                          @click="handleClickVideo"
                          @play="isPlaying=true"
                          @timeupdate="handleTimeUpdate"
                          :style="{'width': `${winWidth}px`, 'height': `${winHeight}px`}"
                      >
                      </video>
                      
                      <!-- 浮層模塊 -->
                      <view class="ulive__video-float__info flexbox flex-col">
                          <view class="flexbox flex-row flex-alignb">
                              <!-- 左側 -->
                              <view class="vdinfo__left flex1 flexbox flex-col">
                                  <view class="ltrow danmu flexbox" @click="handleOpenDanmu"><text class="danmu-txt"></text><uv-icon class="ico" name="edit-pen" color="#fff" size="14" /></view>
                                  <view class="ltrow"><text class="ait">@{{item.author}}</text></view>
                                  <view class="ltrow"><text class="desc">{{item.desc}}</text></view>
                              </view>
                              <!-- 右側操作欄 -->
                              <view class="vdinfo__right flexbox flex-col">
                                  <view class="rtbtn avatar flexbox flex-col">
                                      <view class="ubox"><image class="uimg" :src="item.avatar" mode="aspectFill" /></view>
                                      <view class="btn flexbox" :class="{'active': item.isFollow}" @click="handleFollow(index)"><uv-icon :name="item.isFollow ? 'checkmark' : 'plus'" :color="item.isFollow ? '#ff007f' : '#fff'" size="11" /></view>
                                  </view>
                                  <view class="rtbtn flexbox flex-col" @click="handleLiked(index)"><uv-icon name="heart-fill" :color="item.isLike ? '#ff007f' : '#fff'" size="40" /><text class="num">{{item.likeNum+(item.isLike ? 1 : 0)}}</text></view>
                                  <view class="rtbtn flexbox flex-col" @click="handleOpenComment(index)"><uv-icon name="chat-fill" color="#fff" size="40" /><text class="num">{{item.replyNum}}</text></view>
                                  <view class="rtbtn flexbox flex-col"><uv-icon name="star-fill" color="#fff" size="40" /><text class="num">{{item.starNum}}</text></view>
                                  <view class="rtbtn flexbox flex-col" @click="handleOpenShare(index)"><uv-icon name="share-fill" color="#fff" size="40" /><text class="num">{{item.shareNum}}</text></view>
                              </view>
                          </view>
                      </view>
                  </swiper-item>
              </swiper>
              
              <!-- 固定tabs(脫離滑動區) -->
              <view class="ulive__video-header__tabs" :style="{'margin-top': `${menuBarT}px`}">
                  <uv-tabs :current="tabsCurrent" :list="tabsList" />
              </view>
              
              <!-- 播放暫停按鈕 -->
              <view v-if="!isPlaying" class="ua__swipervideo-playbtn" :style="{'left': `${winWidth/2}px`, 'top': `${winHeight/2}px`}" @click="handleClickVideo">
                  <text class="ua__swipervideo-playico welive-icon welive-icon-play nvueicon"></text>
              </view>
              <!-- 播放mini進度條 -->
              <view class="ua__swipervideo-progress" :style="{'width': `${winWidth}px`}"><view class="ua__swipervideo-progressbar" :style="{'width': `${progressBar}px`}"></view></view>
          </view>
          
          <template #footer>
              <ua-tabbar bgcolor="transparent" color="rgba(255,255,255,.7)" :border="false" :dock="false" transparent z-index="1000" />
          </template>
      </ua-layout>

      uni-welive支持自動播放、發送視頻彈幕、底部Mini視頻播放進度條等功能。

      <script setup>
          import { ref, computed, getCurrentInstance } from 'vue'
          import { onShow, onHide } from '@dcloudio/uni-app'
          import { getRandomColor } from '@/utils'
          
          // ...
          
          const { globalData } = getApp()
          const menuBarT = ref(globalData.menu?.top || globalData.statusBarH)
          const winWidth = ref(globalData.screenWidth)
          const winHeight = ref(globalData.screenHeight)
          
          const tabsList = ref([
              { name: '推薦', count: 5 },
              { name: '關注' },
              { name: '同城' }
          ])
          const tabsCurrent = ref(0)
          
          // 視頻參數
          const currentVideo = ref(0)
          const isPlaying = ref(false)
          const clickNum = ref(0)
          const clickTimer = ref(null)
          const progressBar = ref(0)
          
          // 視頻源
          const videoList = ref(videoJson)
          const danmuEditor = ref('')
          const isVisibleDanmu = ref(false)
          const commentRef = ref(null)
          const shareRef = ref(null)
          
          // ...
          
          
          /**
           * ====================== 視頻播放模塊 ======================
          */
          // 創建并返回 video 上下文 videoContext 對象
          const getVideoContext = () => {
              // return uni.createVideoContext(`uplayer${currentVideo.value}`, this)
              return uni.createVideoContext(`uplayer${currentVideo.value}`, getCurrentInstance())
          }
          
          // 垂直滑動視頻,滑動改變時會觸發 change 事件
          const handleChange = (e) => {
              const index = e.detail.current
              progressBar.value = 0
              handleReset()
              
              currentVideo.value = index
              // 播放
              handlePlay()
          }
          
          // 播放
          const handlePlay = () => {
              console.log('video play')
              let video = getVideoContext()
              if(!video) return
              video.play()
              isPlaying.value = true
          }
          
          // 暫停
          const handlePause = () => {
              console.log('video pause')
              let video = getVideoContext()
              if(!video) return
              video.pause()
              isPlaying.value = false
          }
          
          // 重置播放
          const handleReset = () => {
              console.log('video reset')
              let video = getVideoContext()
              if(!video) return
              video.pause()
              video.seek(0)
              video.stop()
              isPlaying.value = false
          }
          
          // 監聽播放進度條
          const handleTimeUpdate = (e) => {
              let { currentTime, duration } = e.detail
              progressBar.value = parseInt((currentTime / duration).toFixed(2) * parseInt(winWidth.value))
          }
          
          // 點擊視頻(監聽單雙擊)
          const handleClickVideo = () => {
              console.log('video click')
              clearTimeout(clickTimer.value)
              clickNum.value++
              clickTimer.value = setTimeout(() => {
                  if(clickNum.value >= 2) {
                      console.log('double click')
                  }else {
                      if(isPlaying.value) {
                          handlePause()
                      }else {
                          handlePlay()
                      }
                  }
                  clickNum.value = 0
              }, 200)
          }
          
          
          /**
           * ====================== 其它功能模塊 ======================
          */
          // 打開彈幕彈框
          const handleOpenDanmu = () => {
              isVisibleDanmu.value = true
          }
          // 關閉彈幕彈框
          const handleCloseDanmu = () => {
              uni.hideKeyboard()
              isVisibleDanmu.value = false
              danmuEditor.value = ''
          }
          // 發送彈幕
          const handleSendDanmu = () => {
              let video = getVideoContext()
              if(!video) return
              video.sendDanmu({
                  text: danmuEditor.value,
                  color: getRandomColor()
              })
              handleCloseDanmu()
          }
          
          // 打開評論框
          const handleOpenComment = (index) => {
              commentRef.value.open()
          }
          
          // ...
      
      </script>

      注意:uniapp+vue3獲取創建視頻上下文實例,由于vue3沒有this,只能通過getCurrentInstance獲取上下文實例。

      uni.createVideoContext(`uplayer${currentVideo.value}`, getCurrentInstance())

      uniapp+vue3直播模塊

      直播模塊整體分為頂部信息+直播流視頻區+滾動消息(加入直播間+送禮物+講解商品)+底部toolbar欄

      <ua-layout>
          <view class="ua__swipervideo flex1">
              <swiper
                  class="ua__swipervideo-wrap flex1"
                  :current="currentLive"
                  vertical
                  @change="handleChange"
              >
                  <swiper-item v-for="(item, index) in liveList" :key="index">
                      <video
                          class="ua__swipervideo-player flex1"
                          :id="'uplayer' + index"
                          :src="item.src"
                          :controls="false"
                          :loop="true"
                          :autoplay="index == currentLive"
                          :show-center-play-btn="false"
                          object-fit="contain"
                          :style="{'width': `${winWidth}px`, 'height': `${winHeight}px`}"
                      >
                      </video>
                      
                      <!-- 浮層模塊 -->
                      <swiper class="ulive__swiperscreen flex1" :current="1">
                          <!-- 清屏 -->
                          <swiper-item>
                              第一屏
                          </swiper-item>
                          <swiper-item>
                              <!-- 頂部區域 -->
                              <view class="ulive__headlayer" :style="{'top': menuBarT+'px'}">
                                  <!-- logo+關注 -->
                                  <view class="ulive__hd-liveinfo flexbox flex-row flex-alignc">
                                      <view class="ulive__hd-avatar ulive__mask flex-alignc">
                                          <image class="logo" :src="item.logo" mode="widthFix" />
                                          <view class="flex1 flexbox flex-col ml-10">
                                              <text class="name">{{item.name}}</text>
                                              <text class="zan">{{item.likeNum}}本場點贊</text>
                                          </view>
                                          <view class="btn flexbox flex-row flex-alignc" :class="{'active': item.isFollow}" @click="handleFollow(index)"><text class="btntext" :class="{'active': item.isFollow}">{{item.isFollow ? '已關注' : '關注'}}</text></view>
                                      </view>
                                      <view class="ulive__hd-onlineuser flex1">
                                          <uv-icon name="close" color="#fff" @click="handleLiveQuit" />
                                      </view>
                                  </view>
                                  <view class="ulive__hd-livewrap flexbox flex-row">
                                      <view class="ulive__hd-livewrap__left flex1 flexbox flex-col">
                                          <view class="ulive__hd-livewrap__tags flexbox flex-row">
                                              <view class="ulive__roundwrap ulive__mask">
                                                  <uv-icon name="shopping-cart" color="#ffdd1a" /><text class="ulive__roundtext">服飾鞋包榜第1名</text>
                                              </view>
                                              <view class="ulive__roundwrap ulive__mask ml-10">
                                                  <uv-icon name="level" color="#ffdd1a" /><text class="ulive__roundtext">小時榜</text>
                                              </view>
                                          </view>
                                          <!-- 紅包+福袋倒計時 -->
                                          <view class="ulive__hd-livewrap__redpacket flexbox flex-row">
                                              <view class="ulive__redpacket-item ulive__mask" @click="handleOpenRedpacket(1)">
                                                  <image class="ulive__redpacket-image" src="/static/icon-fudai.png" mode="widthFix" /><text class="ulive__redpacket-time">04:49</text>
                                              </view>
                                              <view class="ulive__redpacket-item ulive__mask" @click="handleOpenRedpacket(2)">
                                                  <image class="ulive__redpacket-image" src="/static/icon-hb.png" mode="widthFix" /><text class="ulive__redpacket-time">04:49</text>
                                              </view>
                                              <view class="ulive__redpacket-item ulive__mask center">
                                                  <image class="ulive__redpacket-image" src="/static/icon-rotate.png" mode="widthFix" /><text class="ulive__redpacket-time">04:49</text>
                                              </view>
                                          </view>
                                      </view>
                                      <view class="ulive__hd-livewrap__right flexbox flex-col">
                                          <view class="ulive__roundwrap ulive__mask mr-20">
                                              <uv-icon name="kefu-ermai" color="#fff" /><text class="ulive__roundtext ml-5">后臺</text>
                                          </view>
                                      </view>
                                  </view>
                              </view>
                              
                              <!-- 底部區域 -->
                              <view class="ulive__footlayer">
                                  <!-- 商品提示層 -->
                                  <view class="ulive__ft-livewrap-placeholder animated fadeIn">
                                      <view class="ulive__ft-livewrap-hotbuy flexbox flex-row">
                                          <image class="gimg" :src="item.poster" mode="aspectFill" />
                                          <view class="ginfo flex1">
                                              <view class="flexbox flex-row"><text class="user c-ffdd1a">Andy</text><text class="c-fff">等{{item.saleNum}}人在購買</text></view>
                                              <text class="gdesc clamp1">{{item.desc}}</text>
                                          </view>
                                          <view class="btn"><text class="btntext">去購買</text></view>
                                      </view>
                                  </view>
                                  <!-- 加入直播間/送禮物提示 -->
                                  <view class="ulive__ft-livewrap-animateview flexbox flex-col">
                                      <view class="ulive__ft-livewrap-animatejoin ulive__ft-livewrap-placeholder">
                                          <view v-if="joinRoomData" class="ulive__ft-livewrap-joinroom"><text class="ulive__ft-livewrap-joinroom__text">歡迎{{joinRoomData}}加入了直播間</text></view>
                                      </view>
                                      
                                      <!-- 送禮物 -->
                                      <view class="ulive__ft-livewrap-animategift ulive__ft-livewrap-placeholder">
                                          <view v-if="!isEmpty(sendGiftData)" class="ulive__ft-livewrap-activegift flexbox flex-row flex-alignc">
                                              <image class="avatar" :src="sendGiftData.avatar" />
                                              <view class="info flex1"><text class="name">{{sendGiftData.user}}</text><text class="desc">送出</text></view>
                                              <image class="gift" :src="sendGiftData.pic" />
                                          </view>
                                      </view>
                                  </view>
                                  <!-- 聊天浮層+商品講解 -->
                                  <view class="ulive__ft-livewrap-mixinview flexbox flex-row">
                                      <!-- 聊天消息 -->
                                      <view class="ulive__ft-livewrap-chats flex1">
                                          <scroll-view class="ulive__ft-livewrap-chats__scrollview flex1" scroll-y show-scrollbar="false" :scroll-into-view="scrollToView" :lower-threshold="5" @scroll="handleMsgScroll" @scrolltolower="handleMsgScrollLower">
                                              <block v-for="(msgitem, msgidx) in item.message" :key="msgidx">
                                                  <view v-if="msgitem.type == 'notice'" class="notice" :id="`msg-${msgitem.id}`"><view class="item"><text class="noticetext">{{msgitem.content}}</text></view></view>
                                                  <view v-else-if="msgitem.type == 'gift'" class="gift" :id="`msg-${msgitem.id}`">
                                                      <view class="item">
                                                          <text class="giftuser">{{msgitem.user}}</text>
                                                          <text class="gifttext">送出了{{msgitem.content}}</text>
                                                          <image class="giftimg" :src="msgitem.img" mode="widthFix" />
                                                          <text class="giftnum">x{{msgitem.num}}</text>
                                                      </view>
                                                  </view>
                                                  <view v-else class="msg" :id="`msg-${msgitem.id}`">
                                                      <view class="item">
                                                          <text v-if="msgitem.tag" class="tag">{{msgitem.tag}}</text>
                                                          <text class="user">{{msgitem.user}}</text>
                                                          <text class="text" :style="[fixTextStyle]">{{msgitem.isbuy ? '正在購買' : msgitem.content}}</text>
                                                          <text v-if="msgitem.isbuy" class="tag tag-buy">去購買</text>
                                                      </view>
                                                  </view>
                                              </block>
                                          </scroll-view>
                                          <view v-if="!isEmpty(msgUnread)" class="ulive__ft-livewrap-chats__unread" @click="handleMsgIsRead"><text class="c-eb4868 fs-24">{{msgUnread.length}}條新消息</text></view>
                                      </view>
                                      <!-- 商品講解 -->
                                      <view v-if="isVisibleGoodsTalk" class="ulive__ft-livewrap-activegoods animated fadeInRight" id="goodsTalkID">
                                          <view class="ulive__ft-livewrap-activegoods__hotsale flexbox flex-row">
                                              <image class="fimg" src="/static/icon-hot.png" mode="widthFix" /><text class="c-fff fs-32">熱賣 x{{item.saleNum}}</text>
                                          </view>
                                          <swiper class="ulive__ft-livewrap-activegoods__swiper">
                                              <swiper-item>
                                                  <view class="ulive__ft-livewrap-activegoods__card">
                                                      <view class="gwrap" @click="toGoodsDetail">
                                                          <image class="gimg" :src="item.poster" mode="aspectFill" />
                                                          <view class="waves"><text class="c-fff fs-24">講解中</text></view>
                                                          <view class="close" @click.stop="isVisibleGoodsTalk=false"><uv-icon name="close-circle-fill" color="rgba(0, 0, 0, .3)" size="14" /></view>
                                                      </view>
                                                      <view class="ginfo flexbox flex-col">
                                                          <text class="clamp1 fs-24">{{item.desc}}</text>
                                                          <text class="clamp1 fs-24 c-eb4868">7天無理由退貨</text>
                                                      </view>
                                                      <view class="btn flexbox flex-row"><text class="flex1 c-fff fs-28">¥79.00</text><text class="qiang"></text></view>
                                                  </view>
                                              </swiper-item>
                                          </swiper>
                                      </view>
                                  </view>
                                  <!-- 工具欄 -->
                                  <view class="ulive__ft-livewrap-toolbar flexbox flex-row">
                                      <view class="editorwrap flex1 flexbox flex-row flex-alignc">
                                          <view class="flex1" @click="handleOpenChatbox"><text class="editorwrap-text">說點什么...</text></view>
                                      </view>
                                      <view class="btnwrap flexbox flex-row">
                                          <view class="btn flexbox" @click="handleOpenMenus"><uv-icon name="grid" color="#3c9cff" size="22" /></view>
                                          <view class="btn flexbox" @click="handleOpenGoods(item)"><uv-icon name="shopping-cart-fill" color="#ffaa00" size="24" /></view>
                                          <view class="btn flexbox" @click="handleOpenGifts"><uv-icon name="gift" color="#ff0ad3" size="22" /></view>
                                          <view class="btn flexbox"><uv-icon name="more-dot-fill" color="#efe9ff" size="18" /></view>
                                      </view>
                                  </view>
                              </view>
                          </swiper-item>
                      </swiper>
                  </swiper-item>
              </swiper>
          </view>
      </ua-layout>

      Okay,以上就是uniapp+vue3開發仿微信/抖音短視頻+直播商城的一些知識分享,希望對大家有所幫助哈~~??

      最后附上兩個最近實例項目

      Electron27+React18跨平臺macos桌面系統管理:http://www.rzrgm.cn/xiaoyan2017/p/17850653.html

      Uniapp+Vue3仿制chatgpt會話實例:http://www.rzrgm.cn/xiaoyan2017/p/17507581.html

       

      posted @ 2024-01-01 11:13  xiaoyan2017  閱讀(2988)  評論(0)    收藏  舉報
      友情鏈接: UP主小店B站
      主站蜘蛛池模板: 亚洲av永久无码精品秋霞电影影院| 午夜精品极品粉嫩国产尤物| 午夜亚洲AV日韩AV无码大全| 自治县| 国产视频最新| 国产毛片精品一区二区色| 欧美日韩国产va在线观看免费 | 高清中文字幕国产精品| 亚洲av成人无码天堂| 一本色道久久88亚洲精品综合| 免费看国产精品3a黄的视频| 成人久久精品国产亚洲av| 国产精品原创不卡在线| 午夜免费无码福利视频麻豆| 亚洲精品久久无码av片软件| 韩国免费A级毛片久久| 国产精品久久久天天影视| 久色伊人激情文学你懂的| 人妻av无码系列一区二区三区| 看黄a大片日本真人视频直播| 亚洲高清国产自产拍av| 色吊a中文字幕一二三区| 久久综合激情网| 色婷婷五月综合久久| 九九热在线视频只有精品| 91人妻熟妇在线视频| 国产福利永久在线视频无毒不卡| 国产精品一区二区人人爽| 成人片黄网站色大片免费毛片| 自拍偷自拍亚洲精品熟妇人| 精品国产迷系列在线观看| 免费一本色道久久一区| 午夜福利国产精品小视频| 中国女人和老外的毛片| 成人看的污污超级黄网站免费 | 亚洲色最新高清AV网站| 亚洲国产精品老熟女乱码| 亚欧乱色国产精品免费九库| 国产精品成人午夜福利| 麻豆天美东精91厂制片| 91久久性奴调教国产免费|