uni-app上下滑动播放视频(类抖音)

uni-app 上下滑动播放视频

1、视频列表页

<template>
	<view>
		<view class="f_bottom_box" v-if="videoList.length">
			<view class="bottom_box" v-for="(vo,index) in videoList" :key="index" @click="goXiangqing(vo.id)">
				<image :src="vo.cover" mode="widthFix" class="bot_img" v-if="vo.cover" :lazy-load="true"></image>
				<video @loadeddata="createPreImg($event)" :src="vo.video" mode="widthFix" class="bot_img"
					v-else-if="vo.video"></video>
				<image :src="vo.imageList[0].url" mode="widthFix" class="bot_img" v-else :lazy-load="true"></image>
				<view class="bottom_img_text">
					<view class="text">{{vo.title}}</view>
					<view class="bottom_img" @click.stop>
						<view class="f_img">
							<image :src="vo.touxiang" mode="aspectFill" class="tx"></image>
							<view class="">{{vo.name}}</view>
						</view>
						<u-icon name="heart-fill" color="rgba(216, 32, 70, 1)" size="18" class="love"
							v-if="vo.isdianzan" @click="isLOve(vo.id,0,index)"></u-icon>
						<u-icon name="heart" color="rgba(196, 196, 196, 1)" size="18" class="love" v-else
							@click="isLOve(vo.id,1,index)"></u-icon>
					</view>
				</view>
			</view>
		</view>

	</view>
</template>

<script>
	import app from '../../App.vue';
	export default {
		data() {
			return {
				videoList: [],
			}
		},
		onLoad() {
			this.getVideoList()
		},
		methods: {
			// 获取所有视频列表
			getVideoList() {
				let data = {
					uid: app.globalData.uid
				}
				this.yrApi.request('Zuopin/getVideoList', 'POST', data).then(res => {
					if (res.data.code == 0) {
						this.videoList = res.data.data
					}
				})
			},
			// 跳转到刷视频界面
			goXiangqing(id){
				uni.navigateTo({
					url:`/pages/demo/shipinxiashua?id=${id}&videoList=${JSON.stringify(this.videoList)}`
				})
			}
		}
	}
</script>

<style lang="scss">
	.f_bottom_box {
		// display: flex;
		// align-items: center;
		// // flex-wrap: wrap;
		// overflow: hidden;
		padding: 0 30rpx;
		justify-content: space-between;
		// flex-flow: column wrap;
		// height: 100vh;
		// display: grid;
		// column-count: 2;//想要排成的列数
		// column-gap: 10;
		column-count: 2;
		column-gap: 10px;
		margin: 0 auto;

		.bottom_box {
			// display: inline-block;
			// width: 48%;
			// margin-left: 4%;
			// vertical-align: top;
			border-radius: 10rpx;
			background-color: #fff;
			box-sizing: border-box;
			-webkit-column-break-inside: avoid;
			break-inside: avoid;
			// text-align: center;
			margin-bottom: 20rpx;

			// &:nth-child(2n-1){
			// 	margin-left: 0;
			// }
			.bot_img {
				width: 100%;
				// height: 439rpx;
				border-radius: 10rpx 10rpx 0 0;
			}

			.bottom_img_text {
				box-sizing: border-box;
				padding: 14rpx 13rpx 20rpx 13rpx;

				.text {
					font-size: 30rpx;
					font-weight: 500;
					color: #434342;
					margin-bottom: 10rpx;
				}

				.bottom_img {
					display: flex;
					justify-content: space-between;
					align-items: center;

					.f_img {
						display: flex;
						align-items: center;

						.tx {
							width: 39rpx;
							height: 39rpx;
							border-radius: 50%;
							margin-right: 10rpx;
						}

						view {
							font-size: 22rpx;
							font-weight: 400;
							color: #999999;
							line-height: 30rpx;
						}
					}


					.love {
						width: 30rpx;
						height: 30rpx;
					}
				}
			}
		}
	}
</style>

2、视频详情页

<template>
    <view>
        <view class="uni-padding-wrap">
            <view class="page-section swiper">
                <view class="page-section-spacing">
                    <swiper class="swiper" @change="changefun" @animationfinish="animationfinishfun" :current="current" :circular="false" :vertical="true">
						<block v-if="PayVideo">
							<swiper-item v-for="(item,index) in PayVideo" :key="index">
								<view class="swiper-item uni-bg-black">
									<video
										:custom-cache="false" 
										:show-fullscreen-btn="false"
										:controls="true"
										:show-center-play-btn="false"
										enable-play-gesture
										:initial-time="0"
										class="video" 
										:id="'id'+index" 
										:src="item.video"
										loop
										:enable-progress-gesture="false"
										v-if="index == current"
									>
									</video>
								</view>
							</swiper-item>
						</block>
                    </swiper>
                </view>
            </view>
        </view>
        <view>
            <view class="left">
                <cover-view class="left_box">
                    <cover-view class="ke_context height">{{description}}</cover-view>
					<!-- <cover-view class="auto">
						<cover-view>视频总时长:{{duration || 0}}</cover-view>
					</cover-view> -->
                </cover-view>
            </view>
        </view>
    </view>
</template>
 
<script>
    export default {
        data() {
            return {
                PayVideo: [],
				videoData: {},
				videoList: [],
				description: '',
				current: 0,
				index_: 0,
				videoContext: '',
				duration: '',//总视频时长
            }
        },
        computed: {
        },
		onLoad(options) {
			this.getVideoInfo(parseInt(options.id))
			if(options.videoList) {
				this.videoList = JSON.parse(decodeURIComponent(options.videoList))
			}
		},
        methods: {
			getVideoInfo(id){
				let data = {
					id
				}
				this.yrApi.request('Zuopin/getVideoById', 'POST', data).then(res=>{
					if(res.data.code==0){
						this.videoData = res.data.data;
						this.id = res.data.data.id
						uni.setNavigationBarTitle({
							title:this.videoData.title
						})
						this.description = this.videoData.desc
						this.PayVideo = this.videoList //上下滑动总数据
						this.current = this.PayVideo.findIndex((item) => {
							return item.id === res.data.data.id
						})
						this.duration = res.data.data.videoTime
						// 自动播放当前视频
						this.$nextTick(function() {
							let videoContext = uni.createVideoContext('id' + this.current)
							console.log("index----",videoContext)
							setTimeout(() => {
							      videoContext.play()
							}, 500)
						})
					}else{
						uni.showToast({
							title:res.msg,
							icon:'none'
						})
						// setTimeout(()=>{
						// 	uni.redirectTo({
						// 		url:'/pages/index/index?index=2'
						// 	})
						// },1500)
					}
				})
			},
			// current改变时会触发change 事件
            changefun(e) {
                let current = e.detail.current
				uni.setNavigationBarTitle({
					title: this.PayVideo[current].title
				})
				if(this.PayVideo[current].desc) {
					this.description = this.PayVideo[current].desc
				}
				this.duration = this.PayVideo[current].videoTime
				let videoContext = uni.createVideoContext('id' + this.current)
				videoContext.pause() //停止播放
            },
			// 动画结束时触发
			animationfinishfun(e) {
				let current = e.detail.current
				let videoContext = uni.createVideoContext('id' + this.current)
				videoContext.pause() //停止播放非当前视频
				videoContext = uni.createVideoContext('id' + current)
				videoContext.play() //开始播放当前视频
				this.current = current //保存当前下标 播放下一个视频时停止上一个视频 防止声音重复
			}
        },
    }
</script>
 
<style scoped lang="scss">
    .circle {
        background: rgba(34, 34, 34, 0.4);
        border-radius: 50%;
        z-index: 2;
        height: 70px;
        width: 70px;
        position: fixed;
        top: 0;
        bottom: 441rpx;
        left: 31rpx;
 
        margin: auto;
 
        .red {
            position: absolute;
            top: 0;
            right: 0;
            bottom: 0;
            left: 0;
            margin: auto;
            z-index: 3;
            height: 35px;
            width: 35px;
        }
    }
 
    .swiper {
        height: 100vh;
 
        .swiper-item {
            height: 100vh;
            position: relative;
        }
 
        .uni-bg-black {
            background: black;
        }
    }
 
    .video {
        width: 100%;
        height: 98vh;
        position: relative;
    }
 
    .left_box {
        position: fixed;
        bottom: 90rpx;
        left: 24rpx;
        .ke_context {
			overflow-y: scroll;
			max-height: 300rpx;
			white-space:pre-wrap;
            width: 700rpx;
            font-size: 30rpx;
            font-family: PingFang SC;
            font-weight: 500;
            color: rgba(255, 255, 255, 1);
			white-space:pre-wrap;
            text-shadow: 0px 1px 1px rgba(0, 0, 0, 0.4);
        }
		
		.height {
			margin-bottom: 40rpx;
		}
 
        .ren {
            margin: 20rpx 0;
            font-size: 36rpx;
            font-family: PingFang SC;
            font-weight: bold;
            color: rgba(255, 255, 255, 1);
            text-shadow: 0px 1px 1px rgba(0, 0, 0, 0.4);
        }
 
        .auto {
            display: flex;
            align-items: center;
            width: 310rpx;
            height: 60rpx;
            margin-top: 24rpx;
            opacity: 1;
            border-radius: 8rpx;
            padding-left: 10rpx;
 
            cover-view {
                font-size: 26rpx;
                font-family: PingFang SC;
                font-weight: 500;
                color: rgba(255, 255, 255, 1);
                line-height: 90px;
                text-shadow: 0px 1px 1px rgba(0, 0, 0, 0.4);
            }
 
            cover-image {
                margin-right: 10rpx;
                height: 28rpx;
                width: 26rpx;
            }
        }
 
        .ke {
            display: flex;
            align-items: center;
            width: 310rpx;
            height: 60rpx;
            background: rgba(0, 0, 0, 0.3);
            opacity: 1;
            border-radius: 8rpx;
            padding-left: 10rpx;
 
            cover-view {
                font-size: 26rpx;
                font-family: PingFang SC;
                font-weight: 500;
                color: rgba(255, 255, 255, 1);
                line-height: 90px;
                text-shadow: 0px 1px 1px rgba(0, 0, 0, 0.4);
            }
 
            cover-image {
                margin-right: 10rpx;
                height: 40rpx;
                width: 40rpx;
            }
        }
    }
 
    .H_T {
        z-index: 2;
        width: 100%;
        display: flex;
        box-sizing: border-box;
        position: absolute;
        padding: 0 30rpx;
        background: transparent;
        justify-content: space-between;
 
        .back {
            height: 48rpx;
            width: 48rpx;
        }
 
        .search {
            height: 48rpx;
            width: 48rpx;
        }
    }
 
    .right_box {
        width: 100rpx;
        position: absolute;
        z-index: 2;
        bottom: 60rpx;
        right: 12rpx;
        display: flex;
        flex-direction: column;
 
        .top1 {
            position: relative;
            height: 124rpx;
 
            .avatar_img {
                width: 98rpx;
                height: 98rpx;
                border-radius: 50%;
            }
 
            .add_img {
                position: absolute;
                z-index: 99;
                width: 48rpx;
                height: 48rpx;
                bottom: 10rpx;
                left: 0;
                right: 0;
                margin: 0 auto;
            }
        }
 
        .top2 {
            display: flex;
            flex-direction: column;
            align-items: center;
            margin-top: 37rpx;
 
            .t_img {
                height: 72rpx;
                width: 72rpx;
                margin-bottom: 10rpx;
            }
            
            .font_t {
                font-size: 26rpx;
                font-family: SF Pro Text;
                font-weight: 500;
                color: rgba(255, 255, 255, 1);
 
                text-shadow: 0px 1rpx 1rpx rgba(0, 0, 0, 0.4);
                text-align: center;
            }
        }
 
    }
</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值