前言
前些日子我收到了一个邮件,内容是这个样子的:
随即我就打开了他所说的麦当劳小程序,这不就是下拉二楼的效果么。。。复不复杂先不说,这不妥妥的挑衅么~ 好像我写不出来似的。有求必应,必须安排。何况我也有计划加这个功能。
尝试一:
说干就干,先在社区搜搜看看有没有人搞过这个。不过只搜到了下面这个帖子:
心说我都写小程序了还要自己写结构写动画么,应该不用吧~,而且我的组件库是基于scroll-view封装的。里面新提供了一些属性和方法还挺不错的。比如:
- ScrollViewContext.scrollTo(Object object) 这个方法不是可以设置滚动到指定位置还有动画么
- scrollEnabled 这个设置不是能控制scroll-view什么时候开始滚动么
然后在scroll-view里设置两个一屏高度的view。然后将scroll-view默认先滚动上去一屏。然后下拉的时候在拉下来,是这个思路。然后就开始写起来。
经过努力搞定了。而且在我的三星手机上效果还不错~ 然后我就拿着我的demo开开心心的去找我的朋友(测试小白鼠),用他高贵的苹果体验一下。等他发过来录屏的视频我傻眼了。。。这怎么在ios下往下拖拽没反应?首先我想到了scrollEnabled,我在touchstart的时候开启,touchend的时候设置关闭。是不是他的问题?注释掉之后果然好了。。。能拖动了,但是这往下滑二楼没有自动往下滚啊。这。。。scrollTo也不好使。看一圈文档确定我写的没问题,enhanced啥的我都开启了。没辙文档也不能全信,安卓和开发者工具好使,ios真机不行~
尝试二:
既然科技不行,那就上狠活被~ 新的渲染引擎Skyline看着不错。而且demo里手势协商那个页面不就是我要的效果么。。。改改就能实现了。这些个手势组件,动画方法想想都激动。
不过凡是留个心眼~我先用ios试试,万一不行呢。。。朋友的ios15.6.1运行官方示例没问题。我掏出我的iphone 6 ios12,小程序正常,点开Skyline的页面直接闪退了。。。果断放弃了
最后的实现:
算了还是踏踏实实写动画吧~ 还是那个思路一个view(wapper) 里套两个一屏高度view(floor、page)。往下拖拽的时候设置view的translateY 移动。利用小程序的界面的animation动画会比自己写的css效果流畅一些。
- 先设置外层的wapper默认移动上去一屏高度。
- touchmove计算手拖动的距离, 实时改写translateY
- 松手时判断。当前移动的距离,如果小于屏幕的六分之一则自动回弹,如果大于六分之一小于三分之一,则页面移动到六分之一的位置开启正在刷新状态。如果大于三分之一,直接移动一屏距离将二楼展现出来。
过程写差不多了,而且也提供了插槽和一些搭配的refresh组件。 这还不够~
我又打开了手机里的一些常见的app去看他们的效果,大受启发~ 我发现有的二楼是从中间展开的,有的是从顶部展开的,有的还带有缩放的效果。思考之后也加了进去。。
1. 基础使用
搭配 second-floor-refresh 组件实现文字提示,同时也提供了插槽位置支持您自定义,自定义 refresh 组件请参考 second-floor-refresh 内部的写法
setText
是关键方法
<second-floor
bind:refresh="onRefresh"
bind:secondShow="onSecondShow"
bind:secondBack="onSecondBack"
model:threshold="{{val}}"
class="my-second-floor"
>
<view slot="second-floor"> 二楼区域 </view>
<!-- 刷新组件 -->
<second-floor-refresh slot="second-floor-refresh"></second-floor-refresh>
<!-- 刷新组件 -->
<view>页面主内容</view>
</second-floor>
Page({
data: {
val: 0, // 拖拽的进度值
},
onRefresh() {
// 下拉刷新时执行
},
onSecondShow() {
// 下拉二楼展开之后执行
},
onSecondBack() {
// 下拉二楼关闭之后执行
},
});
2. 可搭配 page-container
很多 app 的下拉二楼效果是下拉之后打开一个新页,搭配 page-container, 在 onSecondShow 方法中控制 page-container 的 show 可以实现,然后利用组件的 back 事件进行关闭
<second-floor
bind:refresh="onRefresh"
bind:secondShow="onSecondShow"
bind:secondBack="onSecondBack"
model:threshold="{{val}}"
class="my-second-floor"
>
<view slot="second-floor"> 二楼区域 </view>
<!-- 刷新组件 -->
<second-floor-refresh slot="second-floor-refresh"></second-floor-refresh>
<!-- 刷新组件 -->
<view>页面主内容</view>
</second-floor>
<page-container
show="{{show}}"
round="{{round}}"
overlay="{{overlay}}"
duration="{{duration}}"
position="{{position}}"
close-on-slide-down="{{false}}"
bindbeforeenter="onBeforeEnter"
bindenter="onEnter"
bindafterenter="onAfterEnter"
bindbeforeleave="onBeforeLeave"
bindleave="onLeave"
bindafterleave="onAfterLeave"
bindclickoverlay="onClickOverlay"
custom-style="{{customStyle}}"
overlay-style="{{overlayStyle}}"
>
<view class="detail-page">
<button type="primary" bindtap="exit">退出</button>
</view>
</page-container>
Page({
data: {
val: 0, // 拖拽的进度值
show: false,
duration: 300,
position: "right",
round: false,
overlay: true,
customStyle: "",
overlayStyle: "",
},
onRefresh() {
// 下拉刷新时执行
},
onSecondShow() {
// 下拉二楼展开之后执行
setTimeout(() => {
this.setData({
show: true,
});
}, 500);
},
onSecondBack() {
// 下拉二楼关闭之后执行
},
exit() {
const secondFloor = this.selectComponent(".my-second-floor");
secondFloor.back().then(() => {
this.setData({ show: false });
});
},
});
3. 可设置下拉二楼的位置
可设置下拉二楼的位置 top、center、bottom。即展开的时候先展示的是二楼的哪个部位
<!-- top -->
<second-floor top></second-floor>
<!-- center -->
<second-floor center></second-floor>
<!-- bottom -->
<second-floor bottom></second-floor>
4. 可设置下拉二楼是否开启缩放动画
就如同微信首页下拉出来小程序列表一样,二楼展开会有一个缩放的效果
<!-- top scale -->
<second-floor top scale></second-floor>
<!-- center scale-->
<second-floor center scale></second-floor>
<!-- bottom scale-->
<second-floor bottom scale></second-floor>
second-floor 配置
参数 | 说明 | 类型 | 默认值 | 版本 |
---|---|---|---|---|
top | 二楼初始位置 | Boolean | false | 3.2.3 |
center | 二楼初始位置 | Boolean | false | 3.2.3 |
bottom | 二楼初始位置 | Boolean | true | 3.2.3 |
scale | 二楼是否开启缩放动画 | Boolean | false | 3.2.3 |
插槽
名称 | 说明 | 可用组件 |
---|---|---|
second-floor | 二楼插槽区域 | - |
second-floor-refresh | 下拉刷新插槽位置 | second-floor-refresh |
methods 方法
名称 | 用法 | 说明 | 版本 |
---|---|---|---|
settriggered | 先获取组件实例:<br/>const secondFloor = this.selectComponent('.my-second-floor'); , 然后调用方法:<br/>secondFloor.settriggered() |
关闭刷新的方法,在 onRefresh 中,数据刷新之后执行,返回 Promise | 3.2.3 |
back | 先获取组件实例:<br/>const secondFloor = this.selectComponent('.my-second-floor'); , 然后调用方法:<br/>secondFloor.back() |
关闭二楼的方法,会触发 onSecondBack, 返回 Promise | 3.2.3 |
events 事件
名称 | 用法 | 说明 | 版本 |
---|---|---|---|
refresh | bind:refresh |
刷新时执行,可执行请求数据,然后执行 settriggered 关闭刷新 |
3.2.3 |
secondShow | bind:secondShow |
二楼打开之后执行 | 3.2.3 |
secondBack | bind:secondBack |
二楼关闭之后执行 | 3.2.3 |
second-floor-refresh 配置
参数 | 说明 | 类型 | 默认值 | 版本 |
---|---|---|---|---|
refreshConfig | second-floor-refresh 组件的设置,详见refreshConfig | Object | { downText: "下拉刷新", loadingText: "正在加载", backText: "返回首页", tipText: "松开刷新", moreText: "继续下拉有惊喜~", color: "#ffffff" } |
3.2.3 |
refreshConfig
参数 | 说明 | 类型 | 默认值 | 版本 |
---|---|---|---|---|
downText | 开始下拉时的文字 | Boolean | false | 3.2.3 |
loadingText | 正在加载时的文字 | Boolean | false | 3.2.3 |
backText | 二楼加载成功之后返回按钮的文字 | Boolean | false | 3.2.3 |
tipText | 松开刷新时的提示文字 | Boolean | false | 3.2.3 |
moreText | 继续下拉的提示文字 | Boolean | false | 3.2.3 |
color | 文字颜色 | Boolean | false | 3.2.3 |
示例 demo
请微信扫码打开小程序查看
skyline 需要微信 iOS 客户端 8.0.30 或以上版本(对应基础库为 2.27.2 或以上版本),可以尝试看看呢,性能更为接近原生的用户体验。
https://developers.weixin.qq.com/community/develop/article/doc/0000023f404748b20e20cd5a466413
能否增加顶部是banner中间是TAB菜单,滑动列表tab可以悬停的例子,感谢
可以让二楼默认露出来一部分吗?