仿快手视频播放

效果展示

首页

在这里插入图片描述

下拉加载

在这里插入图片描述

详情页面

在这里插入图片描述

切换视频

在这里插入图片描述

效果实现

主页详情页?emmm那必须上路由啊

在这里插入图片描述

如图先创建两个路由TouchFish和TouchFishDetail,之后在router/index.js引入

import TouchFish from '@/views/TouchFish/TouchFish.vue'
{
    path: '/touchfish',
    component: TouchFish,
    meta: {
      title: '视频首页'
    }
  },{
    path: '/touchfishdetail/:id',
    component: () => import('@/views/TouchFishDetail/TouchFishDetail.vue'),
    meta: {
      title: '视频详情'
    }
  }

store/touchfish.js

import {defineStore} from 'pinia'

export const touchFishStore = defineStore('touchFishStore',{
    state:() => {
        return {
            shortVideoList:[], // 短视频列表
        }
    },
    actions: {
        setShortVideoList(list){
            this.shortVideoList = list
        }
    },
    persist: {
        enabled:true,
        storage:localStorage,
        key:'TOUCH_FISH_STORE'
    }
})

先介绍两个文件

  • @/config/ksHttpConfig api需要的参数文件
/* 请求随机视频队列的接口配置文件 */

export const ksConfigRandomVidoeListData = {
   query: `fragment photoContent on PhotoEntity {
       __typename
       id
       duration
       caption
       originCaption
       likeCount
       viewCount
       commentCount
       realLikeCount
       coverUrl
       photoUrl
       photoH265Url
       manifest
       manifestH265
       videoResource
       coverUrls {
         url
         __typename
       }
       timestamp
       expTag
       animatedCoverUrl
       distance
       videoRatio
       liked
       stereoType
       profileUserTopPhoto
       musicBlocked
     }
     
     fragment recoPhotoFragment on recoPhotoEntity {
       __typename
       id
       duration
       caption
       originCaption
       likeCount
       viewCount
       commentCount
       realLikeCount
       coverUrl
       photoUrl
       photoH265Url
       manifest
       manifestH265
       videoResource
       coverUrls {
         url
         __typename
       }
       timestamp
       expTag
       animatedCoverUrl
       distance
       videoRatio
       liked
       stereoType
       profileUserTopPhoto
       musicBlocked
     }
     
     fragment feedContent on Feed {
       type
       author {
         id
         name
         headerUrl
         following
         headerUrls {
           url
           __typename
         }
         __typename
       }
       photo {
         ...photoContent
         ...recoPhotoFragment
         __typename
       }
       canAddComment
       llsid
       status
       currentPcursor
       tags {
         type
         name
         __typename
       }
       __typename
     }
     
     fragment photoResult on PhotoResult {
       result
       llsid
       expTag
       serverExpTag
       pcursor
       feeds {
         ...feedContent
         __typename
       }
       webPageArea
       __typename
     }
     
     query brilliantTypeDataQuery($pcursor: String, $hotChannelId: String, $page: String, $webPageArea: String) {
       brilliantTypeData(pcursor: $pcursor, hotChannelId: $hotChannelId, page: $page, webPageArea: $webPageArea) {
         ...photoResult
         __typename
       }
     }
     `,
   variables: {hotChannelId: "00",page:"brilliant",pcursor:"1"}
}
  • @/api/touchFish.js 随机获取快手的视频列表api
   import { ksConfigRandomVidoeListData } from '@/config/ksHttpConfig'
   import {ksHttpInstance} from '@/http/baseHttp/baseHttp.js'

   /**
    * @name getRandomKSvideoList 
    * @description 随机获取快手的视频列表
    * @method POST
    * @path /graphql
    * @returns promise
    */
   export const httpInstanceGetRandomKSvideoList = () => {
       return ksHttpInstance({
           url: "/ksproxy/graphql",
           method: "POST",
           // headers: {"Content-Type":"application/json"},
           data:ksConfigRandomVidoeListData
       })
   }

编写视频首页代码

<script setup>
import { onMounted, reactive, ref} from 'vue';
import {useRouter} from 'vue-router'
import {httpInstanceGetRandomKSvideoList} from '@/api/touchFish.js'
import {HeartIcon} from '@layui/icons-vue'
import {videoList} from '@/config/ksDataConfig' //  获取到的快手短视频数据
import scrollBottom from '@/components/scrollBottom.vue'
import {touchFishStore} from '@/store/touchfish'
let _touchFishStore = touchFishStore()
const router = useRouter()
onMounted(() => {
  getRandomKSvideoList()
})

// 轮播
let touchFishBannerActive = ref("1")
let touchFishBannerConfig = reactive({
  touchFishBannerActive: "1",
  bannerList:[{
    id:"1",
    url:"https://img-baofun.zhhainiao.com/pcwallpaper_ugc/static/8897033871bd3adf2165075e3801628a.jpg?x-oss-process=image%2fresize%2cm_lfit%2cw_3840%2ch_2160"
  },{
    id:"2",
    url:"https://img-baofun.zhhainiao.com/pcwallpaper_ugc/static/479b26fdb8991c71c5b877c2e0fdce4a.jpg?x-oss-process=image%2fresize%2cm_lfit%2cw_3840%2ch_2160"
  },{
    id:"3",
    url:"https://bpic.588ku.com/Templet_origin_pic/05/41/70/8171875aa84b0320eea9f3b840855a2f.jpg"
  },{
    id:"4",
    url:"https://img.zcool.cn/community/015f6958b78944a801219c77f62de2.jpg@2o.jpg"
  },{
    id:"5",
    url:"https://img-baofun.zhhainiao.com/pcwallpaper_ugc/static/58dcba384954105ed097d64f9c0d9d31.jpg?x-oss-process=image%2fresize%2cm_lfit%2cw_3840%2ch_2160"
  }]
})


let brilliantTypeData = reactive({
  feeds:[],
  loading:false
})
/* 获取短视频列表 */
let getRandomKSvideoList = async () => {
  let {data:res} = await httpInstanceGetRandomKSvideoList()
  brilliantTypeData.loading = true
  // let {data:res} = videoList
  brilliantTypeData.loading = true
  brilliantTypeData.feeds = [...brilliantTypeData.feeds,...res.data.brilliantTypeData.feeds]
  _touchFishStore.setShortVideoList(brilliantTypeData.feeds)
  console.log('brilliantTypeData',brilliantTypeData.feeds);
}

/* 下来加载 */
let pushShortVideo = () => {
  getRandomKSvideoList()
}

/* 单个视频点击处理函数 */
let shortVideoClickHandler = (shortVideoItem) => {
  console.log('shortVideoItem',shortVideoItem);
  router.push('/touchfishdetail/'+shortVideoItem.photo.id,)
}


</script>

<template>
  <div class="touch-fish-container">
    <div class="touch-fish-short-video">
      <h1 class="touch-fish-title mr-tb-15">摸鱼短视频</h1>
      <div class="touch-fish-short-video-top mr-tb-15">
        <lay-carousel v-model="touchFishBannerConfig.touchFishBannerActive">
          <lay-carousel-item v-for="item in touchFishBannerConfig.bannerList" :id="item.id" :key="item.id">
            <div :style="{width:'100%',height:'100%',background:`url(${item.url}) 50% 40%`,backgroundSize:'100%'}"></div>
          </lay-carousel-item>
        </lay-carousel>
      </div>
      <div class="touch-fish-short-video-bottom">
        <h1 class="touch-fish-title mr-tb-15">推荐视频</h1>
        <scroll-bottom :obligateBottom="50" @scrollBottom="pushShortVideo">
          <ul class="short-video-list">
            <li class="short-video-item" v-for="item in brilliantTypeData.feeds" :key="item.photo.id" @click="shortVideoClickHandler(item)">
              <img class="short-video-item-cover" v-lazy="item.photo.animatedCoverUrl" alt="" srcset="">
              <div class="short-video-info">
                <p class="author">作者:{{ item.author.name }}</p>
                <p class="caption">{{ item.photo.caption}}</p>
                <p class="like-count">
                  <HeartIcon></HeartIcon>
                  {{ item.photo.likeCount }}
                </p>
              </div>
            </li>
            <i class="short-video-item-zw"></i><i class="short-video-item-zw"></i><i class="short-video-item-zw"></i><i class="short-video-item-zw"></i><i class="short-video-item-zw"></i><i class="short-video-item-zw"></i>
          </ul>
        </scroll-bottom>
        <p class="loading-text mr-tb-15">{{ brilliantTypeData.loading ? '正在加载···' : '我也是有底线的哦~' }}</p>
      </div>
    </div>
  </div>
</template>


<style lang="scss" scoped>
.touch-fish-container {
  width: 100%;
  .touch-fish-short-video {
    width: 1200px;
    min-height: 538px;
    margin: 0 auto;
    .touch-fish-title {
      font-weight: bold;
    }
    .layui-carousel {
      height: 500px !important;
    }
  }

  // video
  .touch-fish-short-video-bottom {
    .short-video-list {
      width: 1200px;
      min-height: 358px;
      flex-wrap: wrap;
      display: flex;
      justify-content: space-between;
      .short-video-item {
        // overflow: hidden;
        width: 185px;
        height: 314px;
        position: relative;
        cursor: pointer;
        margin-bottom: 124px;
        .short-video-item-cover {
          width: 100%;
          height: 100%;
          object-fit: cover;
        }
        .short-video-info {
          padding: 10px 5px;
          position: absolute;
          width: 100%;
          height: 80px;
          bottom: -80px;
          left: 0px;
          color: #000000;
          // background: rgba(0,0,0,.5);
          overflow: hidden;
          .author {
            line-height: 22px;
            font-weight: bold;
            font-size: 12px;
          }
          .caption {
            height: 22px;
            line-height: 22px;
            text-overflow: ellipsis;
            white-space: nowrap;
            overflow: hidden;
            text-align: center;
          }
          .like-count {
            font-size: 12px;
            line-height: 22px;
          }
        }
      }
      .short-video-item-zw {
        width: 185px;
        position: relative;
        margin-bottom: 44px;
      }
    }
    .loading-text {
      text-align: center;
    }
  }
}
</style>

没有什么需要特别说明的,就是下拉加载记得添加一个防抖函数
在这里插入图片描述

详情页面

  • 详情页面所包含的功能较多分步实现~
    • 选用合适的播放器
    • 视频的切换
      • 鼠标滚轮切换
      • 点击页面上下按键切换
      • 当前视频播放完毕自动切换
    • 当前可播放列表全部播放完毕时候由用户选择是重新播放还是刷新当前播放列表
    • 选中当前视频条目,视频标题高亮,自动进入可视区域在侧边栏置顶

西瓜播放器

字节跳动的视频业务大多数是短视频,早期的时候我们在 video.js 基础上做二次开发。后来发现很多功能达不到我们的要求,比如自定义UI的成本、视频的清晰度无缝切换、视频流量的节省。考虑到当前点播依旧是mp4居多,我们做了个大胆的假设:在播放器端加载视频、解析视频、转换格式,让不支持分段播放的mp4动态支持,这样就无须转换源视频的格式,服务器端也无其他开销。在这个动力下,我们在2017年年底完成了这项开发任务,并与2018年年初测试了稳定性和经济收益。在这个背景下,我们一次解析了 hls、flv 等视频,这样我们不再简单的依赖第三方的视频库,只有掌握了底层技术才有优化的可能性。在不断攻克 hls、flv 解析的背景下,我们增强了产品体验,比如交互效果、进场动画等。直到最近,我们想完善文档并把播放器源代码开源出来给更多的视频从业者一个参考,我们一起交流学习,共同进步。

西瓜播放器官网 !!!注意引入时候引入西瓜播放器的样式 官网上面好像没说import 'xgplayer/dist/index.min.css';

视频的切换

鼠标滚轮的切换(根据wheel事件进行监听)
let wheelHandler = (eventData) => {
    /* 判断方向 */
    let isTop = eventData.wheelDelta > 0 ? true : false
    let ID = ''
    let currentIndex = _touchFishStore.shortVideoList.findIndex(item => item.photo.id == id.value) //当前的视频在列表的索引
    // 上一条
    if (isTop) {
        if (currentIndex  == 0 ) {
            layer.close()
            layer.msg('已经是第一条了')
            return
        }

        ID = _touchFishStore.shortVideoList[currentIndex-1].photo.id
        router.push('/touchfishdetail/' + ID)
        
    }else {
        // 下一条
        if (currentIndex == _touchFishStore.shortVideoList.length - 1) {
            layer.closeAll()
            layer.msg('已经是最后一条')
            /* 显示遮罩 */
            isEnd.value = true
            console.log('isEnd',isEnd.value);
            return
        }

        ID = _touchFishStore.shortVideoList[currentIndex+1].photo.id
        console.log('ID',ID);
        router.push('/touchfishdetail/' + ID)

    }
}
点击页面上下按键切换

点击切换与上下滚轮切换的逻辑处理相同(手动传入参数)

<div class="taggle-view">
    <div class="upicon-view" @click="wheelHandler({wheelDelta:1})">
        <UpIcon></UpIcon>
    </div>
    <div class="downicon-view" :class="[isEnd ? 'no-down-video-active' : '']" @click="wheelHandler({wheelDelta:-1})">
        <DownIcon></DownIcon>
    </div>
</div>
视频播放完毕自动切换

未做。可根据xgplayer提供的api监听当前页面的播放结束事件 进行判断进行切换

当前可播放列表全部播放完毕时候由用户选择是重新播放还是刷新当前播放列表

/* 刷新播放列表 */
let refresgHandler = async () => {
    console.log('开始刷新');
    let {data:res} = await httpInstanceGetRandomKSvideoList()
    _touchFishStore.setShortVideoList(res.data.brilliantTypeData.feeds)
    replateVideoView()
}


/* 重新观看 */
let replateVideoView = () => {
    isEnd.value = false
    let ID = _touchFishStore.shortVideoList[0].photo.id
    router.push('/touchfishdetail/' + ID)
} 

选中当前视频条目,视频标题高亮,自动进入可视区域在侧边栏置顶

watch根据当前视频详情路由切换进行监听

watch(() => route.params.id,(newId,oldId) => {
    nextTick(() => {
        isEnd.value = false
        id.value = route.params.id
        videoInfo.info = _touchFishStore.shortVideoList.find(item => item.photo.id == id.value) // 当前视频数据详情
        console.log('当前视频信息',videoInfo.info);
        videoInfo.name = videoInfo.info.photo.caption
        videoInfo.author = videoInfo.info.author.name
        videoInfo.headerUrl = videoInfo.info.author.headerUrl
        url.value = videoInfo.info.photo.photoUrl
        player.src = url.value
        /* 添加切换时候左侧菜单的标题在可视区里面高亮 */
        let dom = document.querySelector(`[data-id='${newId}']`)
        let scrollDom = document.querySelector('.short-video-list')
        scrollDom.scrollTo({
            behavior:"smooth",
            top:dom.offsetTop - 10
        })
    })
},{immediate:true})

完整详情vue文件

<script setup>
import { touchFishStore } from '@/store/touchfish';
import { layer } from '@layui/layui-vue';
import { onMounted, reactive, ref,watch , nextTick} from 'vue'
import { useRoute, useRouter } from 'vue-router';
import Player  from 'xgplayer'
import {RefreshThreeIcon,DownIcon,UpIcon} from '@layui/icons-vue'
import 'xgplayer/dist/index.min.css';
import {debounce} from '@/util/utilFunction'
import {httpInstanceGetRandomKSvideoList} from '@/api/touchFish'

let _touchFishStore = touchFishStore()
const route = useRoute()
const router = useRouter()
/* 当前页面短视频id */
let id = ref('')
let url = ref('')
let isEnd = ref(false)
let videoInfo = reactive({
    info:{},
    name: '',
    author:'',
    headerUrl:'',
    coverUrl: '' // 背景
})

let player = null
/* 创建播放器 */
let initPlayer = () => {
    player = new Player({
        id: "xg-player",
        url:url.value,
        fitVideoSize: 'auto',
        width: 438,
        height: "100%",
        autoplay: true,
        download: true, //设置download控件显示
        loop:true,
        controls:true
    })
}

let shortVideoPlay = ref(null) // 获取节点



/* 切换 */
let updateVideo = (item) => {
    router.push('/touchfishdetail/' + item.photo.id)
}

watch(() => route.params.id,(newId,oldId) => {
    nextTick(() => {
        isEnd.value = false
        id.value = route.params.id
        videoInfo.info = _touchFishStore.shortVideoList.find(item => item.photo.id == id.value) // 当前视频数据详情
        console.log('当前视频信息',videoInfo.info);
        videoInfo.name = videoInfo.info.photo.caption
        videoInfo.author = videoInfo.info.author.name
        videoInfo.headerUrl = videoInfo.info.author.headerUrl
        url.value = videoInfo.info.photo.photoUrl
        player.src = url.value
        /* 添加切换时候左侧菜单的标题在可视区里面高亮 */
        let dom = document.querySelector(`[data-id='${newId}']`)
        let scrollDom = document.querySelector('.short-video-list')
        scrollDom.scrollTo({
            behavior:"smooth",
            top:dom.offsetTop - 10
        })
    })
},{immediate:true})

let wheelHandler = (eventData) => {
    /* 判断方向 */
    let isTop = eventData.wheelDelta > 0 ? true : false
    let ID = ''
    let currentIndex = _touchFishStore.shortVideoList.findIndex(item => item.photo.id == id.value) //当前的视频在列表的索引
    // 上一条
    if (isTop) {
        if (currentIndex  == 0 ) {
            layer.close()
            layer.msg('已经是第一条了')
            return
        }

        ID = _touchFishStore.shortVideoList[currentIndex-1].photo.id
        router.push('/touchfishdetail/' + ID)
        
    }else {
        // 下一条
        if (currentIndex == _touchFishStore.shortVideoList.length - 1) {
            layer.closeAll()
            layer.msg('已经是最后一条')
            /* 显示遮罩 */
            isEnd.value = true
            console.log('isEnd',isEnd.value);
            return
        }

        ID = _touchFishStore.shortVideoList[currentIndex+1].photo.id
        console.log('ID',ID);
        router.push('/touchfishdetail/' + ID)

    }
}

/* 刷新播放列表 */
let refresgHandler = async () => {
    console.log('开始刷新');
    let {data:res} = await httpInstanceGetRandomKSvideoList()
    _touchFishStore.setShortVideoList(res.data.brilliantTypeData.feeds)
    replateVideoView()
}


/* 重新观看 */
let replateVideoView = () => {
    isEnd.value = false
    let ID = _touchFishStore.shortVideoList[0].photo.id
    router.push('/touchfishdetail/' + ID)
} 

onMounted(() => {
    id.value = route.params.id
    videoInfo.info = _touchFishStore.shortVideoList.find(item => item.photo.id == id.value) // 当前视频数据详情
    videoInfo.name = videoInfo.info.photo.caption
    videoInfo.author = videoInfo.info.author.name
    videoInfo.coverUrl = videoInfo.info.photo.coverUrl
    videoInfo.headerUrl = videoInfo.info.author.headerUrl
    url.value = videoInfo.info.photo.photoUrl
    initPlayer()
    shortVideoPlay.value.addEventListener('wheel',wheelHandler)
})

</script>

<template>
    <div class="container-short">
        <div class="mask-bg" :style="{backgroundImage:`url(${videoInfo.coverUrl})`}">
        </div>
        <div class="mask-bg_two">
        </div>
        <div class="container">
            <div class="left-list">
                <div class="hot-title mr-tb-15 pd-lr-15">
                    <h1>推荐视频</h1>
                    <RefreshThreeIcon @click="refresgHandler"></RefreshThreeIcon>
                </div>
                <ul class="short-video-list">
                    <li class="short-video-item mr-tb-15" :data-id="item.photo.id" v-for="item in _touchFishStore.shortVideoList" :key="item.photo.id">
                        <div class="video-left">
                            <img class="video-cover" :src="item.photo.coverUrl" alt="">
                        </div>
                        <div class="video-right">
                            <p class="video-title" :class="[item.photo.id == id ? 'active-title' : '']" @click="updateVideo(item)">{{item.photo.caption}}</p>
                            <p class="viewcount">浏览量:{{item.photo.viewCount}}</p>
                            <p class="like-count">喜欢:{{item.photo.likeCount}}</p>
                        </div>
                    </li>
                </ul>
            </div>
            <div class="short-video-play" ref="shortVideoPlay">
                <div class="short-video-play-container">
                    <div id="xg-player"></div>
                    <div class="short-video-info pd-lr-15">
                        <img :src="videoInfo.headerUrl" class="author-header-url mr-tb-5" alt="" srcset="">
                        <p class="video-author mr-tb-5">@{{videoInfo.author}}</p>
                        <p class="video-title mr-tb-10">{{videoInfo.name}}</p>
                    </div>
                     <!-- 显示刷新弹窗 -->
                    <div class="short-video-play-mask" v-show="isEnd">
                        <lay-button  class="refech-btn" @click="refresgHandler">刷新播放列表</lay-button>
                        <lay-button type="danger"  class="view" @click="replateVideoView">重新观看</lay-button>
                    </div>
                    <!-- 上下视频切换箭头 -->
                    <div class="taggle-view">
                        <div class="upicon-view" @click="wheelHandler({wheelDelta:1})">
                            <UpIcon></UpIcon>
                        </div>
                        <div class="downicon-view" :class="[isEnd ? 'no-down-video-active' : '']" @click="wheelHandler({wheelDelta:-1})">
                            <DownIcon></DownIcon>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>

<style lang="scss" scoped>
.container-short {
    width: 100%;
    height: 100vh;
    position: relative;
    overflow: hidden;

    .mask-bg {
        position: absolute;
        top: 0px;
        width: 100%;
        height: 100%;
        background: #000000;
        // background-image: url('https://p1.a.yximgs.com/upic/2023/08/01/20/BMjAyMzA4MDEyMDIzMjBfMjkxODI3OTkyMV8xMDk0NDA2NDQ4ODNfMV8z_Bd65a14a4c1a5597f4890dfcc5423f5ee.jpg?tag=1-1696643878-xpcwebbrilliant-0-uyv6zebx9w-e5998ce9e73f435c&clientCacheKey=3x58wbhtfrjvfae.jpg&di=3b2781b2&bp=14944');
        background-repeat: no-repeat;
        background-size: 100%;
        transform: scale(1.2);
        opacity: .8;
        filter: blur(15px);
    }

    .mask-bg_two {
        position: absolute;
        left: 0px;
        top: 0px;
        width: 100%;
        height: 100%;
        background: #000;
        opacity: .6;
    }

    .container {
        display: flex;
        position: absolute;
        z-index: 14;
        height: 100%;
        width: 100%;
        left: 0px;
        top: 0px;
        color: #fff;
        .left-list {
            width: 300px;
            height: 100%;
            border-radius: 0px 15px 15px 0px;
            background: rgba(0,0,0,.5);
            .hot-title {
                display: flex;
                align-items: center;
                // justify-content: space-between;
                h1 {
                    display: inline-block;
                    margin-right: 20px;
                }
                ::v-deep .layui-icon-refresh-three {
                    transition: .3s all;
                    cursor: pointer;
                    &:hover{
                        color: red;
                    }
                }
            }
            .short-video-list {
                &::-webkit-scrollbar {
                    display: none;
                }
                position: relative;
                padding-bottom: 15px;
                overflow-y: auto;
                height: calc(100% - 47px);
                .short-video-item {
                    display: flex;
                    flex-direction: row;
                    justify-content: center;
                    align-items: center;
                    width: 100%;
                    height: 80px;
                    overflow: hidden;
                    .video-left {
                        .video-cover {
                            width: 120px;
                            height: 75px;
                            object-fit: cover;
                        }
                    }
                    .video-right {
                        padding: 0px 5px;
                        box-sizing: border-box;
                        display: flex;
                        flex-direction: column;
                        flex-wrap: wrap;
                        justify-content: space-between;
                        width: 180px;
                        height: 100%;
                        overflow: hidden;
                        .video-title {
                            transition: .3s all;
                            width: 100%;
                            display: -webkit-box;
                            -webkit-line-clamp: 2;
                            // text-overflow: ellipsis;
                            // text-overflow: -o-ellipsis-lastline;
                            -webkit-box-orient: vertical;
                            overflow: hidden;
                            cursor: pointer;
                            &:hover {
                                color: red;
                            }
                        }
                        .active-title {
                            color: red;
                        }
                        .viewcount {
                            font-size: 12px;
                            color: #909090;
                        }
                        .like-count {
                            font-size: 12px;
                            color: #909090;
                        }
                    }
                }
            }
        }
        /* 右侧 */
        .short-video-play {
            flex: 1;
            display: flex;
            justify-content: center;
            .short-video-play-container {
                position: relative;
                margin: 0 auto;
                // 显示的刷新的遮罩
                .short-video-play-mask {
                    position: absolute;
                    z-index: 999;
                    display: flex;
                    justify-content: center;
                    align-items: center;
                    top: 0px;
                    left: 0px;
                    width: 100%;
                    height: 100%;
                    background: rgba(0, 0, 0, 0.785);
                    .refech-btn {
                        margin-right: 15px;
                        background: red;
                        color: #fff;
                        outline: none;
                        border: none;
                        border-radius: 0;
                        &:hover {
                            background: rgb(189, 10, 10);
                            color: #fff;
                            opacity: 1;
                        }
                    }
                    .view {
                        margin-left: 15px;
                        outline: none;
                        border: none;
                        border-radius: 0;
                        background: #484847;
                        color: #fff;
                        &:hover {
                            background: #323232;
                            color: #fff;
                            opacity: 1;
                        }
                    }
                }
                .taggle-view {
                    position: absolute;
                    right: -60px;
                    bottom: 100px;
                    border-radius: 25px;
                    padding: 5px 5px;
                    background: rgba(0, 0, 0, 0.307);
                    .upicon-view,.downicon-view {
                        display: flex;
                        justify-content: center;
                        align-items: center;
                        transition: .3s all;
                        cursor: pointer;
                        margin: 10px 0px;
                        padding: 10px 0px;
                        border-radius: 50%;
                        width: 40px;
                        height: 40px;
                    }
                    .upicon-view:hover {
                            background: rgba(0, 0, 0, 0.821);
                    }
                    .downicon-view:hover {
                        background: rgba(0, 0, 0, 0.821);
                    }
                    /* 如果是最后一个视频时候 */
                    .no-down-video-active {
                        color: #575757;
                        pointer-events: none;
                    }
                }
            }
            .short-video-info {
                width: 40%;
                position: absolute;
                bottom: 60px;
                left: 0px;
                .author-header-url {
                    width: 45px;
                    height: 45px;
                    border-radius: 15px;
                }
            }
        }
    }
}

</style>

原文链接在我的博客

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值