Recently, I wrote a project using tiktok like pages, which would enlarge and increase the top background when the top user performs the pull down operation, making the page feel more slippery. First up effect:
There is a complete code at the end of the article. You can jump directly to the end of the article in a hurry.
Before you code, learn about several events:
@touchstart when the user's finger is pressed
@touchmove when the user's finger moves
@touchend when the user raises his finger
These events will record the position information of the user's fingers on the screen and page. There is also a life cycle event of uniapp, onPageScroll(), which monitors the page scrolling.
!!! These events must be bound to the outermost tag and listen to the whole page!!!
The implementation idea of this function is as follows:
Step 1: first monitor whether the current position is the top of the page viewport onPageScroll(), and then monitor the user's finger movements.
Step 2: when the viewport is at the top of the page and the user makes a pull-down action, dynamically modify the height and width of the top background image (magnification effect).
Step 3: when the user raises his finger @ touchend, restore the picture to its original width and height.
According to our ideas, it is realized step by step with code:
Step 1: first monitor whether the current position is the top of the page viewport onPageScroll(), and then monitor the user's finger movements.
<view class="my" @touchmove="move" @touchend="end"> //Binding listening events: when the user's finger moves and when the user's finger lifts </view> <script> export default { data() { return { // User operation clientData: { // User Finger Y axis clientMoveY: '', //Press clientEndY: '', //lift // Page Y axis pageY: '' } } }, onPageScroll(e) { //Gets the scroll height of the current page this.clientData.pageY = e.scrollTop; }, methods: { // Finger movement move(e) { }, // Finger lift end(e) { }, } } </script>
Step 2: when the viewport is at the top of the page and the user makes a pull-down action, dynamically modify the height and width of the top background image. (I use transform:scale() to enlarge the picture here)
onPageScroll(e) { //Gets the scroll height of the current page this.clientData.pageY = e.scrollTop; }, methods: { // Finger press start(e) { let touch = e.changedTouches[0]; this.clientData.clientStartY = e.changedTouches[0].clientY; }, // Finger movement move(e) { // First determine whether the user has reached the top if (this.clientData.pageY < 1) { // The comparison between the position of this finger movement and the position of the last movement < 1 proves that the user is pulling down if(this.clientData.clientMoveY - e.changedTouches[0].clientY < 1) { // Get the pull-down distance let distance = this.clientData.clientMoveY - e.changedTouches[0].clientY; // Drop down to 800rpx at most and enlarge by 1.8x if(this.sheight < 800 && this.imgWidth < 1.8){ this.sheight -= distance this.imgWidth -= distance/500 }else{//return if it exceeds 800 or 1.8 times return } }else{ return // After the execution of the above code, assign the position of this finger to data for the next comparison this.clientData.clientMoveY = e.changedTouches[0].clientY; } }, // Finger lift end(e) { } }
Step 3: when the user raises his finger @ touchend, restore the picture to its original width and height.
Here, we need to define an animation first. When the user raises his finger, the animation is executed:
// An animation .isPlay { animation: big 0.5s 1 alternate ease-in-out forwards; } @keyframes big { 100% { transform: scale(1);//The magnification of the picture is restored to 1 height: 400rpx;//Restore height to original height } }
The isPlay class name needs to be dynamically bound to the image. When the animation is executed, it is bound to execute the animation. When the animation is finished, contact and wait for the next trigger event.
end(e) { // console.log('finger lift ', e); // this.clientData.clientEndY = e.changedTouches[0].clientY; // When the height of the picture is greater than 400, raise your finger and call the function again if (this.sheight > 400) { // Execute animation this.isPlay = true; // After the animation, the height and magnification of the top picture will be changed to the original value setTimeout(() => { this.sheight = 400; this.imgWidth = 1; // And cancel the class name of the animation this.isPlay = false; }, 504);//My definition of animation here is the end of 0.5s } },
This is probably the idea. Dynamic binding and some small places are written one by one.
There must be many ways to achieve this effect. This is only one of them. For example, the image can be enlarged by directly changing the width of the image.
Full code:
<template> <view class="my" @touchend="end" @touchmove="move"> <!-- Top background --> <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,//height imgWidth:1,//enlarge scale isPlay:false,//Play animation // User sliding clientData: { // User Finger Y axis clientMoveY: '', //Press clientEndY: '', //lift // Page Y axis pageY: '' }, }; }, onLoad() { }, onPageScroll(e) { //Gets the scroll height of the current page this.clientData.pageY = e.scrollTop; }, methods: { // Finger movement move(e) { // First determine whether the user has reached the top if (this.clientData.pageY < 1) { // The comparison between the position of this finger movement and the position of the last movement < 1 proves that the user is pulling down if(this.clientData.clientMoveY - e.changedTouches[0].clientY < 1) { // Get the pull-down distance let distance = this.clientData.clientMoveY - e.changedTouches[0].clientY; // Drop down to 800rpx at most and enlarge by 1.8x if(this.sheight < 800 && this.imgWidth < 1.8){ this.sheight -= distance this.imgWidth -= distance/500 }else{//Over 800 or 1.8x return to optimize performance return } }else{ return } // After the execution of the above code, assign the position of this finger to data for the next comparison this.clientData.clientMoveY = e.changedTouches[0].clientY; } }, // Finger lift end(e) { this.clientData.clientEndY = e.changedTouches[0].clientY; // When the height of the picture is greater than 400, raise your finger and call the function again if(this.sheight > 400){ // Execute animation this.isPlay = true // After the animation, the height and magnification of the top picture will be changed to the original value setTimeout(()=>{ this.sheight=400 this.imgWidth=1 // And cancel the class name of the animation this.isPlay = false },504) } } } }; </script> <style lang="scss" scoped> .banner { width: 100vw; overflow: hidden;//Prevent the picture from being enlarged and the width from being spread background-size: cover; position: relative; image { width: 100%; max-height: 800rpx; position: absolute; bottom: 0; } } // An animation .isPlay{ animation: big 0.5s 1 alternate ease-in-out forwards; } @keyframes big{ 100% { transform: scale(1); height: 400rpx; } } </style>
Come on, you can grow up with any comments!
Friends who feel useful can also pay attention to me. Interesting functions encountered in the later development process will be synchronized to the blog.