文章目录 1. 实现效果 2. 精简版核心代码 3. 完整功能点(本文章不写,只写核心代码)
1. 实现效果
2. 精简版核心代码
使用的 vue3
+ vant 4
组件 使用van-swipe
进行轮播图切换实现
< template> < div :style = " {width: width + 'px',overflow: 'hidden',}" class = " container" > < van-swipe :loop = " true" vertical :height = " height" :width = " width" :show-indicators = " false" @change = " onChange" :style = " { height: height + 'px' }" > < van-swipe-item v-for = " (item, index) in video List" :key = " index" class = " swiper-slide-item" > < div @click = " onVideoClick(item, index)" z-index = " 1" class = " swiperItemVideo" > < video class = " video Player" :id = " ' video Player_' + index" ref = " player" :key = " index" :poster = " item.poster" :src = " item.src" :width = " width" autoplay :muted = " muteding" loop x5-video -player-type = " h5" webkit-playsinline = " true" x-webkit-airplay = " true" x5-video -orientation = " portraint" playsInline = " true" x5-video -player-fullscreen = " portraint" x5-video -ignore-metadata = ' true' > </ video > < van-image v-if = " !playing" class = " play w-[40px] h-[40px]" :src = " getAssetsFile('icon/play.png')" /> </ div> < ShortsBottom ref = " bottomRef" :item = " item" /> </ van-swipe-item> </ van-swipe> </ div>
</ template>
< script setup lang = " ts" name = " Setting" >
import { getAssetsFile
} from '@/utils/tool'
const player = ref ( null ) ;
const currentIndex = ref ( 0 ) ;
const playing = ref ( true ) ;
const muteding = ref ( true )
const width = ref ( window. innerWidth) ;
const height = ref ( window. innerHeight) ;
let bottomRef = ref ( null )
let bottomHeight = ref ( 0 ) ;
const currentVideoInfo = ref ( { video Id: "" ,
} ) ;
const onChange = ( index ) => { console. log ( index, "index" ) currentVideoInfo. value = { video Id: "" } ; const preVideoId = "video Player_" + currentIndex. value; const preVideo : any = document. getElementById ( preVideoId) ; if ( preVideo) preVideo. pause ( ) ; const nextVideoId = "video Player_" + index; const nextVideo : any = document. getElementById ( nextVideoId) ; if ( nextVideo) nextVideo. play ( ) ; currentIndex. value = index; player. value = nextVideo; playing. value = true if ( index == video List. length - 1 ) { console. log ( "没有更多了" ) }
} ;
const onVideoClick = ( item, index ) => { const video : any = document. getElementById ( "video Player_" + index) ; if ( video && playing. value) { video . pause ( ) ; playing. value = false ; } else { video . play ( ) ; playing. value = true ; }
} ; onMounted ( ( ) => { if ( bottomRef. value) { console. log ( bottomRef. value[ 0 ] . bottomHeight, 1 ) bottomHeight. value = bottomRef. value[ 0 ] . bottomHeight} const index = currentIndex. value; const video s: any = document. querySelectorAll ( "video " ) ; for ( const video of video s) { let video Id = "video Player_" + index; if ( video && video . id && video . id != video Id) { video . pause ( ) ; } else { player. value = video ; } }
} ) ; onBeforeUnmount ( ( ) => { const video s: any = document. querySelectorAll ( "video " ) ; for ( const video of video s) { if ( video && video . id) { video . pause ( ) ; } }
} ) ;
const video List = [ { video Id: Date. now ( ) + 1 , title : "抖音美女主播,JK超短裙学生妆美女跳舞展示,爱了爱了。" , poster : "http://img01.sogoucdn.com/app/a/201023/27e5400e26fbef1ea32f9aff60c0b015" , src : "https://txmov2.a.yximgs.com/upic/2020/11/08/19/BMjAyMDExMDgxOTQxNTlfNTIzNDczMzQ0XzM4OTQ1MDk5MTI4XzFfMw==_b_Bc770a92f0cf153407d60a2eddffeae2a.mp4" , uploadTime : "2023-11-08 19:41" , ipLocation : "上海" , author : { authorId : 101 , avatar : "https://i02piccdn.sogoucdn.com/4f85fc70df81d04a" , nickName : "陌路" , genderName : "男" }
} ,
{ video Id: Date. now ( ) + 2 , title : "御姐美女抖音作品,来个自拍视频把,好美啊。" , poster : "http://img02.sogoucdn.com/app/a/201023/0866f6a339e58d647eb476f72045e980" , src : "https://txmov2.a.yximgs.com/upic/2020/10/02/09/BMjAyMDEwMDIwOTAwMDlfMTIyMjc0NTk0Ml8zNjk3Mjg0NjcxOF8xXzM=_b_B28a4518e86e2cf6155a6c1fc9cf79c6d.mp4" , uploadTime : "2023-10-02 09:41" , ipLocation : "贵州" , author : { authorId : 102 , avatar : "http://img02.sogoucdn.com/app/a/201023/0866f6a339e58d647eb476f72045e980" , nickName : "御姐呀" , genderName : "女" }
} ,
{ video Id: Date. now ( ) + 3 , title : "抖音主播可爱妹子新学的舞蹈,超可爱的美女主播。" , poster : "https://i02piccdn.sogoucdn.com/2acf176d90718d73" , src : "https://txmov6.a.yximgs.com/upic/2020/08/23/00/BMjAyMDA4MjMwMDMyNDRfMTYzMzY5MDA0XzM0ODI4MDcyMzQ5XzFfMw==_b_B9a1c9d4e3a090bb2815994d7f33a906a.mp4" , uploadTime : "2023-08-23 00:41" , ipLocation : "广州" , author : { authorId : 103 , avatar : "https://i02piccdn.sogoucdn.com/2acf176d90718d73" , nickName : "野花猫" , genderName : "女" }
} ,
{ video Id: Date. now ( ) + 4 , title : "多个美女带着遮阳帽出去散步自拍视频,好好看。" , poster : "https://i02piccdn.sogoucdn.com/45c34c84c106bbb7" , src : "https://alimov2.a.yximgs.com/upic/2020/07/02/14/BMjAyMDA3MDIxNDUyMDlfOTExMjIyMjRfMzE1OTEwNjAxNTRfMV8z_b_Bf3005d42ce9c01c0687147428c28d7e6.mp4" , uploadTime : "2023-07-02 14:41" , ipLocation : "山西" , author : { authorId : 104 , avatar : "https://i02piccdn.sogoucdn.com/45c34c84c106bbb7" , nickName : "蓝姬" , genderName : "女" }
} ,
] ;
</ script>
< style lang = " less" scoped >
.container { display : flex; flex-direction : column; overflow : hidden; .swiper-wrapper { flex : 1; } .swiper-slide-item { display : flex; flex-direction : column; width : 100%; .swiperItemVideo { z-index : 1; flex : 1; overflow-y : auto; width : 100%; position : relative; .play { position : absolute; z-index : 2; content : "" ; top : 50%; left : 50%; transform : translate ( -50%, -50%) ; animation : move 0.3s linear alternate; } } .video Player { background : #000; height : 100%; z-index : 2; } }
} @keyframes move { 0% { transform : translate ( -50%, -50%) scale ( 2) ; opacity : 0; } 100% { transform : translate ( -50%, -50%) scale ( 1) ; opacity : 1; }
}
</ style>
ShortsBottom 组件代码
< template> < div class = "video Info" ref= "bottomRef" > < div class = "top mb-[8px]" > < van- image class = "logo w-[40px] h-[40px] mr-[8px]" round : src= "getAssetsFile('logo.png')" / > < span class = "nickName mr-[12px]" > { { item. author. nickName } } < / span> < div class = "btn-content" @ click = "Follow" > < van- button type= "primary" size= "small" class = "btn" > Follow< / van- button> < / div> < div class = "closeSound" > < van- image class = "logo w-[16px] h-[16px]" : src= "getAssetsFile('icon/closeSound.png')" / > < / div> < / div> < van- text- ellipsis class = "title" : content= "item.title" / > < / div>
< / template>
< script setup lang= "ts" > import { ref, onMounted } from "vue" ; import { getAssetsFile } from '@/utils/tool' interface Props { item : any ; } const props = withDefaults ( defineProps < Props> ( ) , { item: { } , } ) ; let bottomRef = ref ( null ) let bottomHeight = ref ( 0 ) const Follow = ( ) => { console . log ( "关注" ) } onMounted ( ( ) => { if ( bottomRef. value) { bottomHeight. value = bottomRef. value. offsetHeight} } ) ; defineExpose ( { bottomHeight } )
< / script> < style lang= "less" scoped> . video Info { background: #161616 ; color: #f5f5f5; padding: 16px 20px 34px 16px; text- align: left; position: relative; & : : after { position: absolute; display: block; content: "" ; bottom: 0px; left: 0 ; width: 100 % ; height: 0px; background: red; z- index: 1 ; } . top { display: flex; justify- content: flex- start; align- items: center; . nickName { font- family: HarmonyOS Sans SC , HarmonyOS Sans SC ; font- weight: 700 ; font- size: 14px; color: #FFFFFF ; line- height: 14px; } . closeSound { margin- left: auto; width: 32px; height: 32px; padding: 8px; border- radius: 50 % ; background: rgba ( 255 , 255 , 255 , 0.1 ) ; } } . title { font- family: HarmonyOS Sans SC , HarmonyOS Sans SC ; font- weight: 400 ; font- size: 14px; color: #FFFFFF ; line- height: 14px; } }
< / style>
3. 完整功能点(本文章不写,只写核心代码)
视频点赞 视频分享 视频用户基础信息 视频暂停/播放 视频声音控制 上下切换视频 视频封面图设置