[微信小程序]微信小程序制作类通讯录的可滑动字母索引效果
1、前言
今天要开发类通讯录的可滑动字母索引效果,搜遍了百度也没找到相关的代码,都是只能点击,不能滑动。
其实这个功能不难实现,各位大神应该是不屑提起。这篇文章只是作为记录,如果能给初学者带来一点帮助就更好了。
2、先上效果图:
3、思路
小程序不能操作DOM,只能通过setData
来改变dom状态。但是,小程序提供了获取元素位置的能力:createSelectorQuery
,并且touchmove
方法也提供了手指所在的坐标信息。所以可以通过判断手指是否进入了索引元素,来决定数据列表跳转的位置。通过setData
来改变scrollIntoView
,使scroll-view
跳转到指定的id
所在的位置。具体参考微信小程序开发文档的scroll-view
组件。
4、实现
首先需要一个scrollView用来显示列表:
<scroll-view scroll-y scroll-into-view='{{scrollIntoView}}'>
<!-- 用来定位 -->
<view id='A' class='index'>A</view>
<view class='item'>这里是列表</view>
</scroll-view>
字母索引部分的布局如下(仅仅是示例):
<view class='index-box' catch:touchmove='touchmove'>
<view class='index' data-id='A'>A</view>
<view class='index' data-id='B'>B</view>
<view class='index' data-id='C'>C</view>
......
</view>
可以声明一个数组来存储所有索引元素的位置信息:
wx.createSelectorQuery()
.selectAll('.index-box .index')
.boundingClientRect()
.exec(function(res) {
arrTouchBarPosition = res[0]; // 需要预先定义arrTouchBarPosition
});
获取到的信息结构如下:
[{
bottom: 93.5,
dataset: { id: "A" },
height: 19,
id: "",
left: 381,
right: 414,
top: 74.5,
width: 33
},......]
其中的top
和bottom
是用来和touchmove
事件中的坐标信息比对的。touchmove
事件如下:
let clientY = e.touches[0].clientY;
for (let item of arrTouchBarPosition) {
if (clientY >= item.top && clientY <= item.bottom) {
this.setData({
scrollIntoView: item.dataset.id
});
break;
}
}
到这里,想要的效果已经实现了。但是为了提高性能,我们可以加上节流和其他减少触发touchmove
事件的条件。最终完整的touchmove
事件函数如下:
touchmove(e) {
// 节流,需要预先定义timestamp
let now = new Date().getTime();
if (now - timestamp < 50) {
return;
}
timestamp = now;
// 无意触发
if (e.touches.length > 1) {
return;
}
let clientY = e.touches[0].clientY;
for (let item of arrTouchBarPosition) {
// 如果已经在目标位置,则不执行
if (clientY >= item.top && clientY <= item.bottom) {
if (item.dataset.id == this.data.scrollIntoView) {
break;
}
this.setData({
scrollIntoView: item.dataset.id
});
break;
}
}
}
如果显示的列表比较长,最好关闭scroll-view
的动画效果。如果不关闭,可能会在操作比较快时,手指已经离开屏幕很长时间,动画还在继续……
即使是关闭了动画,操作较快时也会有同样的问题,但加上节流后问题完美解决。
考虑到需求和性能问题,没有添加在手指滑动到某个字母时,屏幕中间显示该字母的效果。后期将添加这个效果,并封装成一个插件发布到github。
欢迎评论和互动。