手把手教你用前端實(shí)現(xiàn)短視頻App(滑動(dòng)切換)
作者:maomin9761 
  平常在玩短視頻App時(shí),喜歡看的視頻可以多看一會(huì),不喜歡看的視頻直接往上一劃,這個(gè)功能一直深受用戶喜愛(ài)。今天我們不妨實(shí)現(xiàn)一個(gè)這樣功能的App。
 前言
平常在玩短視頻App時(shí),喜歡看的視頻可以多看一會(huì),不喜歡看的視頻直接往上一劃,這個(gè)功能一直深受用戶喜愛(ài)。今天我們不妨實(shí)現(xiàn)一個(gè)這樣功能的App。
功能
- 上下滑動(dòng)切換視頻
 - 可查看對(duì)應(yīng)視頻下的評(píng)論
 
示例
下面我挑出了幾張代表性的圖片,供大家參考。


下載鏈接
以上是我自己做的一款A(yù)pp的示例圖,如果感興趣的小伙伴,大家可以下載到手機(jī)上體驗(yàn)。目前只是開(kāi)發(fā)了安卓版本。
- 鏈接: https://pan.baidu.com/s/1dbgx9eht54qh-Ig04w2JAg
 - 提取碼: 96ta
 - 復(fù)制這段內(nèi)容后打開(kāi)百度網(wǎng)盤(pán)手機(jī)App,操作更方便哦
 
核心代碼
- <template>
 - <div class="home">
 - <van-swipe
 - style="height: 100vh"
 - vertical
 - @change="onChange"
 - :show-indicators="false"
 - >
 - <van-swipe-item>
 - <div class="main" v-if="isshow">
 - <video-player
 - v-if="playerOptions.sources[0].src"
 - class="video-player vjs-custom-skin"
 - ref="videoPlayer"
 - :playsinline="true"
 - :options="playerOptions"
 - ></video-player>
 - <div class="footbox">
 - <div class="foot">
 - <p class="user">@ {{ artistName }}</p>
 - <p class="name">{{ name }}</p>
 - </div>
 - <div class="pl" @click="openPl">
 - <van-icon name="chat" size="30" />
 - </div>
 - </div>
 - </div>
 - </van-swipe-item>
 - <van-swipe-item>
 - <div class="main" v-if="!isshow">
 - <video-player
 - v-if="playerOptions.sources[0].src"
 - class="video-player vjs-custom-skin"
 - ref="videoPlayer"
 - :playsinline="true"
 - :options="playerOptions"
 - ></video-player>
 - <div class="footbox">
 - <div class="foot">
 - <p class="user">@ {{ artistName }}</p>
 - <p class="name">{{ name }}</p>
 - </div>
 - <div class="pl" @click="openPl">
 - <van-icon name="chat" size="30" />
 - </div>
 - </div>
 - </div>
 - </van-swipe-item>
 - </van-swipe>
 - <van-action-sheet v-model="show" class="sheet">
 - <van-list
 - v-model="loading"
 - @load="onLoad"
 - :offset="1"
 - :immediate-check="false"
 - >
 - <div v-for="(item, index) in plist" :key="index" class="ovf pll">
 - <div class="pl-l"><img :src="item.user.avatarUrl" alt="" /></div>
 - <div class="pl-r">
 - <div class="name1">{{ item.user.nickname }}</div>
 - <div class="con">{{ item.content }}</div>
 - </div>
 - </div>
 - </van-list>
 - </van-action-sheet>
 - </div>
 - </template>
 - <script>
 - import { list, mv, pl } from "@request/api";
 - import "../video/index";
 - import { videoPlayer } from "vue-video-player";
 - export default {
 - name: "home",
 - data() {
 - return {
 - list: "",
 - id: "",
 - show: false,
 - dataLength: 1,
 - inx: 0,
 - artistName: "",
 - name: "",
 - isshow: true,
 - plist: "",
 - loading: false,
 - page: 10,
 - playerOptions: {
 - autoplay: true, //如果true,瀏覽器準(zhǔn)備好時(shí)開(kāi)始回放。
 - muted: false, // 默認(rèn)情況下將會(huì)消除任何音頻。
 - loop: false, // 導(dǎo)致視頻一結(jié)束就重新開(kāi)始。
 - preload: "auto", // 建議瀏覽器在<video>加載元素后是否應(yīng)該開(kāi)始下載視頻數(shù)據(jù)。auto瀏覽器選擇最佳行為,立即開(kāi)始加載視頻(如果瀏覽器支持)
 - language: "zh-CN",
 - poster:"",
 - aspectRatio: "16:9", // 將播放器置于流暢模式,并在計(jì)算播放器的動(dòng)態(tài)大小時(shí)使用該值。值應(yīng)該代表一個(gè)比例 - 用冒號(hào)分隔的兩個(gè)數(shù)字(例如"16:9"或"4:3")
 - fluid: true, // 當(dāng)true時(shí),Video.js player將擁有流體大小。換句話說(shuō),它將按比例縮放以適應(yīng)其容器。
 - sources: [{ type: "video/mp4", src: "" }],
 - width: document.documentElement.clientWidth,
 - notSupportedMessage: "此視頻暫無(wú)法播放,請(qǐng)稍后再試", //允許覆蓋Video.js無(wú)法播放媒體源時(shí)顯示的默認(rèn)信息。
 - controlBar: {
 - timeDivider: true, // 分時(shí)
 - durationDisplay: true, // 持續(xù)時(shí)間顯示
 - remainingTimeDisplay: false, // 剩余時(shí)間顯示
 - fullscreenToggle: false, //全屏按鈕
 - },
 - },
 - };
 - },
 - components: {
 - videoPlayer,
 - },
 - mounted() {
 - this.wait();
 - },
 - methods: {
 - // 首次獲取url
 - async wait() {
 - let id = await this.get();
 - let res = await mv(id);
 - // this.playerOptions.poster = this.poster;
 - this.$set(this.playerOptions, "poster", this.poster);
 - this.$set(this.playerOptions.sources[0], "src", res.data.url);
 - },
 - // 加載評(píng)論
 - onLoad() {
 - setTimeout(() => {
 - this.page += 10;
 - this.getpl();
 - this.loading = false;
 - }, 500);
 - },
 - // 獲取數(shù)據(jù)
 - get() {
 - return list(this.dataLength).then((res) => {
 - console.log(res.data);
 - this.urlData = res.data;
 - this.poster = this.urlData[this.inx].cover;
 - this.id = this.urlData[this.inx].id;
 - this.artistName = this.urlData[this.inx].artistName;
 - this.name = this.urlData[this.inx].name;
 - // return this.id;
 - return Promise.resolve(this.id);
 - // 等價(jià)于
 - // return new Promise((resolve) => {
 - // resolve(this.id)
 - // })
 - });
 - },
 - // 封裝靜態(tài)數(shù)據(jù)
 - getStatic(v) {
 - this.id = v[this.inx].id;
 - this.artistName = v[this.inx].artistName;
 - this.name = v[this.inx].name;
 - this.poster = v[this.inx].cover;
 - return this.id;
 - },
 - // 獲取評(píng)論
 - getpl() {
 - pl(this.id, this.page).then((res) => {
 - if (document.querySelector(".van-action-sheet__content")) {
 - document.querySelector(".van-action-sheet__content").scrollTop = 0;
 - }
 - this.plist = res.comments;
 - });
 - },
 - // 滑動(dòng)觸發(fā)
 - async onChange() {
 - console.log(this.inx);
 - this.isshow = !this.isshow;
 - this.page = 10;
 - this.getpl();
 - if (this.inx < this.urlData.length - 1) {
 - this.inx += 1;
 - let id = this.getStatic(this.urlData);
 - let res = await mv(id);
 - this.$set(this.playerOptions.sources[0], "src", res.data.url);
 - this.$set(this.playerOptions, "poster", this.poster);
 - // this.playerOptions.poster = this.poster;
 - } else {
 - this.inx = 0;
 - this.dataLength += 1;
 - this.wait();
 - }
 - },
 - // 打開(kāi)評(píng)論列表
 - openPl() {
 - this.show = true;
 - this.getpl();
 - },
 - },
 - };
 - </script>
 - <style lang="less" scoped>
 - .main {
 - height: 100%;
 - }
 - .footbox {
 - position: relative;
 - bottom: 0;
 - width: 95%;
 - margin: 0 auto;
 - display: flex;
 - justify-content: space-between;
 - align-items: center;
 - }
 - .user {
 - font-size: 14px;
 - }
 - .user,
 - .name {
 - text-overflow: ellipsis;
 - overflow: hidden;
 - white-space: nowrap;
 - }
 - .foot {
 - width: 80%;
 - color: #fff;
 - font-size: 16px;
 - z-index: 10001;
 - }
 - .pl {
 - width: 10%;
 - color: #fff;
 - font-size: 16px;
 - z-index: 10001;
 - }
 - .sheet {
 - height: 50vh;
 - .pll {
 - overflow: hidden;
 - padding: 10px;
 - border-bottom: 1px solid #f4f4f4;
 - .pl-l {
 - width: 20%;
 - float: left;
 - }
 - .pl-l img {
 - width: 55%;
 - border-radius: 50%;
 - animation: all ds 0.5s;
 - }
 - @keyframes ds {
 - from {
 - opacity: 0;
 - }
 - to {
 - opacity: 1;
 - }
 - }
 - .pl-r {
 - width: 78%;
 - float: left;
 - }
 - .name1 {
 - font-size: 14px;
 - color: #666;
 - font-weight: bold;
 - margin-bottom: 5px;
 - }
 - .con {
 - width: 100%;
 - line-height: 24px;
 - color: #333333;
 - font-size: 14px;
 - }
 - }
 - }
 - </style>
 
完整代碼庫(kù)
恭請(qǐng)各位大佬指正。
https://github.com/maomincoding/zm_mv2
責(zé)任編輯:姜華 
                    來(lái)源:
                    前端歷劫之路
 















 
 
 


 
 
 
 