手把手教你用前端实现短视频App(滑动切换)

开发 前端
平常在玩短视频App时,喜欢看的视频可以多看一会,不喜欢看的视频直接往上一划,这个功能一直深受用户喜爱。今天我们不妨实现一个这样功能的App。

[[351990]]

 前言

平常在玩短视频App时,喜欢看的视频可以多看一会,不喜欢看的视频直接往上一划,这个功能一直深受用户喜爱。今天我们不妨实现一个这样功能的App。

功能

  1. 上下滑动切换视频
  2. 可查看对应视频下的评论

示例

下面我挑出了几张代表性的图片,供大家参考。



下载链接

以上是我自己做的一款App的示例图,如果感兴趣的小伙伴,大家可以下载到手机上体验。目前只是开发了安卓版本。 

  1. 链接: https://pan.baidu.com/s/1dbgx9eht54qh-Ig04w2JAg  
  2. 提取码: 96ta  
  3. 复制这段内容后打开百度网盘手机App,操作更方便哦 

核心代码

  1. <template> 
  2.   <div class="home"
  3.     <van-swipe 
  4.       style="height: 100vh" 
  5.       vertical 
  6.       @change="onChange" 
  7.       :show-indicators="false" 
  8.     > 
  9.       <van-swipe-item> 
  10.         <div class="main" v-if="isshow"
  11.           <video-player 
  12.             v-if="playerOptions.sources[0].src" 
  13.             class="video-player vjs-custom-skin" 
  14.             ref="videoPlayer" 
  15.             :playsinline="true" 
  16.             :options="playerOptions" 
  17.           ></video-player> 
  18.           <div class="footbox"
  19.             <div class="foot"
  20.               <p class="user">@ {{ artistName }}</p> 
  21.               <p class="name">{{ name }}</p> 
  22.             </div> 
  23.             <div class="pl" @click="openPl"
  24.               <van-icon name="chat" size="30" /> 
  25.             </div> 
  26.           </div> 
  27.         </div> 
  28.       </van-swipe-item> 
  29.       <van-swipe-item> 
  30.         <div class="main" v-if="!isshow"
  31.           <video-player 
  32.             v-if="playerOptions.sources[0].src" 
  33.             class="video-player vjs-custom-skin" 
  34.             ref="videoPlayer" 
  35.             :playsinline="true" 
  36.             :options="playerOptions" 
  37.           ></video-player> 
  38.           <div class="footbox"
  39.             <div class="foot"
  40.               <p class="user">@ {{ artistName }}</p> 
  41.               <p class="name">{{ name }}</p> 
  42.             </div> 
  43.             <div class="pl" @click="openPl"
  44.               <van-icon name="chat" size="30" /> 
  45.             </div> 
  46.           </div> 
  47.         </div> 
  48.       </van-swipe-item> 
  49.     </van-swipe> 
  50.     <van-action-sheet v-model="show" class="sheet"
  51.       <van-list 
  52.         v-model="loading" 
  53.         @load="onLoad" 
  54.         :offset="1" 
  55.         :immediate-check="false" 
  56.       > 
  57.         <div v-for="(item, index) in plist" :key="index" class="ovf pll"
  58.           <div class="pl-l"><img :src="item.user.avatarUrl" alt="" /></div> 
  59.           <div class="pl-r"
  60.             <div class="name1">{{ item.user.nickname }}</div> 
  61.             <div class="con">{{ item.content }}</div> 
  62.           </div> 
  63.         </div> 
  64.       </van-list> 
  65.     </van-action-sheet> 
  66.   </div> 
  67. </template> 
  68.  
  69. <script> 
  70. import { list, mv, pl } from "@request/api"
  71. import "../video/index"
  72. import { videoPlayer } from "vue-video-player"
  73. export default { 
  74.   name"home"
  75.   data() { 
  76.     return { 
  77.       list: ""
  78.       id: ""
  79.       show: false
  80.       dataLength: 1, 
  81.       inx: 0, 
  82.       artistName: ""
  83.       name""
  84.       isshow: true
  85.       plist: ""
  86.       loading: false
  87.       page: 10, 
  88.       playerOptions: { 
  89.         autoplay: true, //如果true,浏览器准备好时开始回放。 
  90.         muted: false, // 默认情况下将会消除任何音频。 
  91.         loop: false, // 导致视频一结束就重新开始。 
  92.         preload: "auto", // 建议浏览器在<video>加载元素后是否应该开始下载视频数据。auto浏览器选择最佳行为,立即开始加载视频(如果浏览器支持) 
  93.         language: "zh-CN"
  94.         poster:""
  95.         aspectRatio: "16:9", // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9""4:3") 
  96.         fluid: true, // 当true时,Video.js player将拥有流体大小。换句话说,它将按比例缩放以适应其容器。 
  97.         sources: [{ type: "video/mp4", src: "" }], 
  98.         width: document.documentElement.clientWidth, 
  99.         notSupportedMessage: "此视频暂无法播放,请稍后再试", //允许覆盖Video.js无法播放媒体源时显示的默认信息。 
  100.         controlBar: { 
  101.           timeDivider: true, // 分时 
  102.           durationDisplay: true, // 持续时间显示 
  103.           remainingTimeDisplay: false, // 剩余时间显示 
  104.           fullscreenToggle: false, //全屏按钮 
  105.         }, 
  106.       }, 
  107.     }; 
  108.   }, 
  109.   components: { 
  110.     videoPlayer, 
  111.   }, 
  112.   mounted() { 
  113.     this.wait(); 
  114.   }, 
  115.   methods: { 
  116.     // 首次获取url 
  117.     async wait() { 
  118.       let id = await this.get(); 
  119.       let res = await mv(id); 
  120.       // this.playerOptions.poster = this.poster; 
  121.       this.$set(this.playerOptions, "poster", this.poster); 
  122.       this.$set(this.playerOptions.sources[0], "src", res.data.url); 
  123.     }, 
  124.     // 加载评论 
  125.     onLoad() { 
  126.       setTimeout(() => { 
  127.         this.page += 10; 
  128.         this.getpl(); 
  129.         this.loading = false
  130.       }, 500); 
  131.     }, 
  132.     // 获取数据 
  133.     get() { 
  134.       return list(this.dataLength).then((res) => { 
  135.         console.log(res.data); 
  136.         this.urlData = res.data; 
  137.         this.poster = this.urlData[this.inx].cover; 
  138.         this.id = this.urlData[this.inx].id; 
  139.         this.artistName = this.urlData[this.inx].artistName; 
  140.         this.name = this.urlData[this.inx].name
  141.         // return this.id; 
  142.         return Promise.resolve(this.id); 
  143.         // 等价于 
  144.         // return new Promise((resolve) => { 
  145.         //   resolve(this.id) 
  146.         // }) 
  147.       }); 
  148.     }, 
  149.     // 封装静态数据 
  150.     getStatic(v) { 
  151.       this.id = v[this.inx].id; 
  152.       this.artistName = v[this.inx].artistName; 
  153.       this.name = v[this.inx].name
  154.       this.poster = v[this.inx].cover; 
  155.       return this.id; 
  156.     }, 
  157.     // 获取评论 
  158.     getpl() { 
  159.       pl(this.id, this.page).then((res) => { 
  160.         if (document.querySelector(".van-action-sheet__content")) { 
  161.           document.querySelector(".van-action-sheet__content").scrollTop = 0; 
  162.         } 
  163.         this.plist = res.comments; 
  164.       }); 
  165.     }, 
  166.     // 滑动触发 
  167.     async onChange() { 
  168.       console.log(this.inx); 
  169.       this.isshow = !this.isshow; 
  170.       this.page = 10; 
  171.       this.getpl(); 
  172.       if (this.inx < this.urlData.length - 1) { 
  173.         this.inx += 1; 
  174.         let id = this.getStatic(this.urlData); 
  175.         let res = await mv(id); 
  176.         this.$set(this.playerOptions.sources[0], "src", res.data.url); 
  177.         this.$set(this.playerOptions, "poster", this.poster); 
  178.         // this.playerOptions.poster = this.poster; 
  179.       } else { 
  180.         this.inx = 0; 
  181.         this.dataLength += 1; 
  182.         this.wait(); 
  183.       } 
  184.     }, 
  185.     // 打开评论列表 
  186.     openPl() { 
  187.       this.show = true
  188.       this.getpl(); 
  189.     }, 
  190.   }, 
  191. }; 
  192. </script> 
  193. <style lang="less" scoped> 
  194. .main { 
  195.   height: 100%; 
  196. .footbox { 
  197.   position: relative
  198.   bottom: 0; 
  199.   width: 95%; 
  200.   margin: 0 auto; 
  201.   display: flex; 
  202.   justify-content: space-between
  203.   align-items: center; 
  204. .user { 
  205.   font-size: 14px; 
  206. .user
  207. .name { 
  208.   text-overflow: ellipsis; 
  209.   overflow: hidden; 
  210.   white-space: nowrap; 
  211. .foot { 
  212.   width: 80%; 
  213.   color: #fff; 
  214.   font-size: 16px; 
  215.   z-index: 10001; 
  216. .pl { 
  217.   width: 10%; 
  218.   color: #fff; 
  219.   font-size: 16px; 
  220.   z-index: 10001; 
  221. .sheet { 
  222.   height: 50vh; 
  223.   .pll { 
  224.     overflow: hidden; 
  225.     padding: 10px; 
  226.     border-bottom: 1px solid #f4f4f4; 
  227.     .pl-l { 
  228.       width: 20%; 
  229.       floatleft
  230.     } 
  231.     .pl-l img { 
  232.       width: 55%; 
  233.       border-radius: 50%; 
  234.       animation: all ds 0.5s; 
  235.     } 
  236.     @keyframes ds { 
  237.       from { 
  238.         opacity: 0; 
  239.       } 
  240.       to { 
  241.         opacity: 1; 
  242.       } 
  243.     } 
  244.     .pl-r { 
  245.       width: 78%; 
  246.       floatleft
  247.     } 
  248.     .name1 { 
  249.       font-size: 14px; 
  250.       color: #666; 
  251.       font-weight: bold; 
  252.       margin-bottom: 5px; 
  253.     } 
  254.     .con { 
  255.       width: 100%; 
  256.       line-height: 24px; 
  257.       color: #333333; 
  258.       font-size: 14px; 
  259.     } 
  260.   } 
  261. </style> 

 完整代码库

恭请各位大佬指正。

https://github.com/maomincoding/zm_mv2

 

责任编辑:姜华 来源: 前端历劫之路
相关推荐

2021-08-09 13:31:25

PythonExcel代码

2022-10-19 14:30:59

2021-12-11 20:20:19

Python算法线性

2017-10-27 10:29:35

人脸识别UbuntuPython

2017-10-29 21:43:25

人脸识别

2011-03-28 16:14:38

jQuery

2021-02-06 14:55:05

大数据pandas数据分析

2021-02-04 09:00:57

SQLDjango原生

2022-08-04 10:39:23

Jenkins集成CD

2009-04-22 09:17:19

LINQSQL基础

2021-03-23 09:05:52

PythonExcelVlookup

2021-02-10 09:34:40

Python文件的压缩PyCharm

2021-09-02 08:56:48

JavaBMIHashSet

2021-01-21 09:10:29

ECharts柱状图大数据

2021-01-08 10:32:24

Charts折线图数据可视化

2021-05-10 06:48:11

Python腾讯招聘

2020-03-08 22:06:16

Python数据IP

2021-08-02 23:15:20

Pandas数据采集

2021-02-02 13:31:35

Pycharm系统技巧Python

2012-01-11 13:40:35

移动应用云服务
点赞
收藏

51CTO技术栈公众号