场景:
当页面滚动高度超过元素1高度时,元素2(动画的)显示或隐藏。
在小程序中如何做到滚动监听并动态获取元素高度呢?
在开发者工具中预览效果
解决思路:
1.在页面渲染完成后(onReady函数里) 去获取元素1在页面上距离顶部的高度fixedTop;
2.用监听页面滚动函数 onPageScroll得到当前页面滚动高度,注意,这里得到的高度是“页面在垂直防线已滚动的距离(单位px)” ;
- 如上动图可知,元素1距离页面顶部的高度 = 页面已滚动的距离 + 一个平面的高度
- 用wx.getSystemInfo获得设备信息,其中设备的屏幕高度字段为res.screenHeight
具体解决过程:
我们先来看看不考虑现实隐藏的效果的实现过程
.js
文件
/**
* 监听用户滑动页面事件--返回页面在垂直方向已滚动的距离(单位px)
*/
onPageScroll(e){
let isfixed = 0
if(parseInt(e.scrollTop) + parseInt(this.data.screenHeight) > this.data.fixedTop) isfixed = 1
else isfixed = 0;
this.setData({isfixed });
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
let query = wx.createSelectorQuery();
query.select('#notic').boundingClientRect(res => { //获取元素1距离页面顶部高度
this.setData({
fixedTop: res.top
})
}).exec()
wx.getSystemInfo({ //获取屏幕高度
success: (res => {
this.setData({
screenHeight: res.screenHeight
})
})
})
},
.wxml 文件
<view wx:if="{{isfixed}}" class="btn">附近更多活动(我是元素2)</view>
动态的控制isfixed,就可以控制到元素2的显示隐藏啦。
注意一点, wx.createSelectorQuery()获取元素的top值是指元素的margin之外的开始计算的。这里我给 元素2 设置了50的margin,为了计算的精确性,我们应该高度判断的语句减去 元素2 的margin值,例如 if(parseInt(e.scrollTop) + parseInt(this.data.screenHeight) - 100 > this.data.fixedTop) isfixed = 1
下面来看看是怎么加显示隐藏的动画的。
实现方法:用小程序的动画api实现 或 css过度实现
下来来看具体实现过程:
方法1. 小程序wx.createAnimation api实现。
createAnimation具体的用法可看官方文档,这里只说动图的实现效果,实现代码如下:
<view wx:if="{{isfixed}}" animation="{{animate}}" class="btn">附近更多活动(我是元素2)</view>
上图(animation.png)可以看到,先是创建一个动画函数opacityAnimate
,然后在onPageScroll函数中当满足条件时调用该0动画函数,我们给动画传一个为1的值,而css的opacity: 1时即透明度为0,即元素显示。而条件不满足时传0,元素透明,即不显示。
在wxml文件中,动画用animation属性来绑定,如上的wxml代码。
这里我同时用了wx:if 和 animation ,从前面我们知道wx:if就可以控制元素的显示隐藏,只是想要看到过度效果,所以后面加了animation动画。那么这里可不可只写animation来控制显隐呢,答案是可以的,但是animation我们控制的是元素的透明度,元素隐藏只是透明度为0,元素实际上是还在的。这种情况下,如果元素中绑定了事件,点击到透明的元素,一样会触发到绑定事件,所以以防万一还是用wx:if和animation同时控制妥当些。
方法2. 用css过度实现
在控制元素的opacity属性时,可以给元素加一个transition过度属性,看起来就有个动画效果不会那么生硬了。
具体实现如下:
<view
wx:if="{{isfixed}}"
class="btn"
style="transition: all 0.3s;opacity: {{isfixedShow ? 1 : 0}};"
>附近更多活动(我是元素2)</view>
用transition来过度一个元素的opacity时要注意一点,,这个元素必须是先存在的,然后再去控制opacity。如上例子,
wxml文件中,元素同时用来isfixed
和 isfixedShow
两个字段来控制。
js文件中(红框部分)isfixedShow
是根据isfixed
变化后的100ms后才变换的,为什么要延迟呢?其实延迟多长时间可以自己酌情控制,这里想说的是“一个元素的opacity的属性想用transition来过度时,这个元素必须是先存在的”,即先有这个元素(isfixed为true) ,然后再去控制元素的透明度opacity的值。