0
点赞
收藏
分享

微信扫一扫

uniapp(H5,App端) 顶部背景图下拉放大,松开回弹

sin信仰 2022-04-17 阅读 138

最近写项目要用到类似抖音的我的页面,在顶部用户执行下拉操作时顶部背景图会放大并高度增加的效果,使页面感觉更加的丝滑。先上效果:

文章末尾有完整的代码,着急用的可以直接跳转的文章最后。

上代码之前先了解几个事件:

@touchstart 当用户手指按下时

@touchmove 当用户手指移动过程中

@touchend 当用户手指抬起时

这几个事件会记录用户手指在屏幕和页面上的位置信息,还有一个uniapp的生命周期事件onPageScroll()监听页面滚动。

        !!!这几个事件一定要绑定在最外层的标签上,监听整个页面!!!

这个功能的实现思路大概是:

第一步:先监听到当前位置是不是页面视口的顶部onPageScroll(),再监听用户手指的动作。

第二步:当视口位于页面的顶部并且用户做了下拉动作,则动态的修改顶部背景图的高度,宽度(放大效果)。

第三步:当用户手指抬起时@touchend,将图片恢复到原来到宽高。

        按照我们的思路一步一步用代码实现:

第一步:先监听到当前位置是不是页面视口的顶部onPageScroll(),再监听用户手指的动作。

<view class="my"  @touchmove="move" @touchend="end">
    //绑定监听事件,当用户手指移动时和用户手指抬起时
</view>

<script>
export default {
    data() {
		return {
            // 用户操作
			clientData: {
				// 用户手指Y轴
				clientMoveY: '', //按下
				clientEndY: '', //抬起
				// 页面Y轴
				pageY: ''
			}
        }
    },
    onPageScroll(e) {
		//获取当前页面滚动高度
		this.clientData.pageY = e.scrollTop;
	},
    methods: {
		// 手指移动
		move(e) {
		},
		// 手指抬起
		end(e) {
		},
	}
}
</script>

第二步:当视口位于页面的顶部并且用户做了下拉动作,则动态的修改顶部背景图的高度,宽度。(我这里图片给图片放大用的是transform:scale()

onPageScroll(e) {
		//获取当前页面滚动高度
		this.clientData.pageY = e.scrollTop;
	},

	methods: {
		// 手指按下
		start(e) {
			let touch = e.changedTouches[0];
			this.clientData.clientStartY = e.changedTouches[0].clientY;
		},
		// 手指移动
		move(e) {
			// 先判断用户是否到达了顶部
			if (this.clientData.pageY < 1) {
				// 本次手指移动的位置和上次移动的位置对比 <1 证明用户在下拉
				if(this.clientData.clientMoveY - e.changedTouches[0].clientY < 1) {
					// 拿到下拉的距离
					let distance = this.clientData.clientMoveY - e.changedTouches[0].clientY;
					// 最大下拉到800rpx ,放大1.8倍大小
					if(this.sheight < 800 && this.imgWidth < 1.8){
						this.sheight -= distance
						this.imgWidth -= distance/500
					}else{//超过800或者1.8倍就return
						return
					}
				}else{
                    return	
				// 上边的代码执行结束之后再把本次手指的位置赋值给data中,用来下一次对比
				this.clientData.clientMoveY = e.changedTouches[0].clientY;
			}
		},
		// 手指抬起
		end(e) {

		}
	}

第三步:当用户手指抬起时@touchend,将图片恢复到原来到宽高。

这里我们需要先定义一个动画,当用户手指抬起是执行这个动画:

// 一个动画
.isPlay {
	animation: big 0.5s 1 alternate ease-in-out forwards;
}
@keyframes big {
	100% {
		transform: scale(1);//图片放大比例恢复为1
		height: 400rpx;//高度恢复为原来的高度
	}
}

这个isPlay的class名需要动态的绑定给image,执行动画时绑定上,执行动画,当动画执行完,接触,等待下一次触发事件。

end(e) {
	// console.log('手指抬起', e);
	// this.clientData.clientEndY = e.changedTouches[0].clientY;
	// 当图片的高度大于400的时候手指抬起再调用函数
	if (this.sheight > 400) {
		// 执行动画
		this.isPlay = true;
		// 动画结束后把顶部图片的高度和放大比例该会原来的值
		setTimeout(() => {
			this.sheight = 400;
			this.imgWidth = 1;
			// 并把动画的class名取消掉
			this.isPlay = false;
		}, 504);//我这里动画定义的是0.5s结束
	}
},

大概就是这么个思路,动态绑定和一些小的地方就一一写出来了。

这个效果的实现肯定有很多种,这只是其中的一种,比如图片放大效果,也可以直接更改图片的宽度来实现放大。

完整代码:

<template>
	<view class="my" @touchend="end" @touchmove="move">
		<!-- 顶部背景图 -->
		<view :class="{'banner':true,'isPlay':isPlay}" :style="{ height: sheight + 'rpx' }">
			<view class="">
				<image :class="{'isPlay':isPlay}" :style="{ height: sheight + 'rpx',transform:`scale(${imgWidth})`}" src="https://p4.music.126.net/nILBk4DaE3yV__25uq-5GQ==/18641120139241412.jpg?param=640y300" mode=""></image>
			</view>
		</view>
	</view>
</template>

<script>
export default {
	components: {
	},
	data() {
		return {
			sheight: 400,//高度
			imgWidth:1,//放大比例
			isPlay:false,//是否播放动画
			// 用户滑动
			clientData: {
				// 用户手指Y轴
				clientMoveY: '', //按下
				clientEndY: '', //抬起
				// 页面Y轴
				pageY: ''
			},
		};
	},
	onLoad() {
	},
	onPageScroll(e) {
		//获取当前页面滚动高度
		this.clientData.pageY = e.scrollTop;
	},

	methods: {
		// 手指移动
		move(e) {
			// 先判断用户是否到达了顶部
			if (this.clientData.pageY < 1) {
				// 本次手指移动的位置和上次移动的位置对比 <1 证明用户在下拉
				if(this.clientData.clientMoveY - e.changedTouches[0].clientY < 1) {
					// 拿到下拉的距离
					let distance = this.clientData.clientMoveY - e.changedTouches[0].clientY;
					// 最大下拉到800rpx ,放大1.8倍大小
					if(this.sheight < 800 && this.imgWidth < 1.8){
						this.sheight -= distance
						this.imgWidth -= distance/500
					}else{//超过800或者1.8倍就return 优化性能
						return
					}
				}else{
					return
				}
				// 上边的代码执行结束之后再把本次手指的位置赋值给data中,用来下一次对比
				this.clientData.clientMoveY = e.changedTouches[0].clientY;
			}
		},
		// 手指抬起
		end(e) {
			this.clientData.clientEndY = e.changedTouches[0].clientY;
			// 当图片的高度大于400的时候手指抬起再调用函数
			if(this.sheight > 400){
				// 执行动画
				this.isPlay = true
				// 动画结束后把顶部图片的高度和放大比例该会原来的值
				setTimeout(()=>{
						this.sheight=400
						this.imgWidth=1
						// 并把动画的class名取消掉
						this.isPlay = false
				},504)
			}
		}
	}
};
</script>

<style lang="scss" scoped>
.banner {
	width: 100vw;
	overflow: hidden;//防止图片放大,宽度被撑开
	background-size: cover;
	position: relative;
	image {
		width: 100%;
		max-height: 800rpx;
		position: absolute;
		bottom: 0;
	}
}
// 一个动画
.isPlay{
	animation: big 0.5s 1 alternate ease-in-out forwards;
}
@keyframes big{
	100% {
		transform: scale(1);
		height: 400rpx;
	}
}
</style>

代码中有任何建议,可以评论下来,一起成长,加油!

感觉有用的小伙伴也可以关注我,后期在开发过程中遇到有趣的功能都会同步到博客上。

举报

相关推荐

0 条评论