作为一个工作了两年多的前端,每次写移动端项目的时候,经常会碰到滚筒选择器的需求,比如电商类选择收货地址,比如互金类选择商品品类等,相信大家写移动端项目的时候也碰到过需要滚筒选择器的需求。不得不说,就移动端而言,滚筒选择器选择品类或者地址交互确实蛮流畅的,对用户来说也是很舒服的一种用户体验,但是个人觉的开源的UI框架好像没好用或者说刚好满足需求的现成的滚筒选择器组件,综上,我决定自己手撸一个滚筒选择器。
先来了解一下滚筒选择器需要做到的功能和交互,这里先放一张我写的滚筒选择器的效果图
这里我直接放的是屏幕截图(因为我懒得做一个gif图放上去了哈哈哈哈,各位看官将就着看吧),可以看到这里的滚筒我是放了三列,三列是独立的,实际上组件我只写了一列,然后v-for循环了三个哈哈哈哈哈,只是在外层容器用flex把他们平铺到一行去了。
好了废话也不多说了,先来说说思路吧,首先我们要的是一个数据列表,然后中间给个高亮表示选中的数据,换句话说,没选中的部分给个遮罩让他们看起来模模糊糊的就好了是吧,滚动的时候让数据能在高亮行(即上图中两条蓝线区域,下文同理)中居中显示就好了。刚开始我本来想直接CSS来实现,后来只能做出个样子,交互效果很一般,因为高亮行上下都有一层灰蒙蒙的遮罩,导致能滚动的区域只有高亮行这么一小块区域,并且让数据列滚筒时不能自动把数据在高亮行内居中(可能表达的不是很清楚,总之一句话就是,单纯CSS写滚筒,交互效果不好),所以我放弃了,然后我开始各种百度,终于让我找到了一个比较好的我能理解的demo了,这里附上demo原git地址(本来想放原文地址的,后来找不到了,这里跟原作者说个不好意思),这个demo给提供了一个新的思路,html部分,原作者分了三个部分,一个高亮区域和两个数据列,通过position和transform+translate来固定位置,讲道理这个是我之前没有想到的,或许这就是菜鸡与大神之前的区别把。好了接下来我们来看一下代码吧。
这里要着重说的两个样式transform-style: preserve-3d; 和 backface-visibility: hidden;
(1)transfrom-style 属性规定如何在3D空间呈现被嵌套的元素,值如下图:
我们使用preserve-3d 是让我们的值列表呈现3d效果,他是写在列表父级的;
(2)backface-visivility 属性定义当元素不面向屏幕时是否可见,值如下图:
我们使用hidden是背面不可见的,他是写在列表上的。这两个属性单独拿出来讲并不是属性有多难,只是比较少见而已,不过只有他们是无法完成这个艰巨界面的。
接下来我们来看看js部分吧,我觉的js部分才是这个组件的有趣之处。
因为是移动端,所以我们要重手指触摸到屏幕那刻开始处理,刚开始触摸touchstart的时候给一个itemTouchStrat事件,滑动的时候touchmove给个itemTouchMove事件,触摸结束touchend的时候给个itemTouchEnd事件,然后我们想想这些时间段里我们要做那些事情,你就能想到,在itemTouchStart和itemTouchEnd里我们要保存当前触摸的位置和当前触摸的时间,为什么呢,因为滚筒选择器里有一个相当于惯性滚动的后续效果,所以我们得知道用户手指滑动的位移和时间,用于后面计算惯性滚动的位移量,即开始时间和结束时间以及move的位移量。因为我们html里把选中的和可供选择的数据分开了,也就说灰蒙蒙的那些数据跟高亮的数据实际上是不搭嘎的,只是我们通过一些操作让他们联动了起来,所以我们在touchmove的时候也要知道位移时间和位移量,用于改变高亮数据样式。好接下来就是最关键的问题,我手离开屏幕之后,滚筒依旧在滚动并在一段时间停下来并选中这个效果要怎么实现呢,实际上,我们只要知道手指离开之后滚动的位移量是多少就行了,然后我们用这个位移量去除以单条数据的高度就能知道最后会选中那条数据了对吧,好的那就涉及到touchend触发时滚动的加速度了,但是!这种高中物理知识!像我这种辣鸡肯定是解不出来的哈哈哈所以在这块没多做纠缠,直接跟着原作者走了哈哈哈哈哈。那么到这里基本上就搞定了对不对,这里把滚动时改CSS代码贴出来
看官们,你们品!你们细品!是不是觉的有点好玩,反正我觉的挺好玩的哈哈哈哈哈。
对了因为是移动端项目,所以兼容各个设备宽度自然是要做的,这里我用的是postcss-pxtorem,一个PostCSS的插件,用于将像素单元生成rem单位,因为js改变css的时候里面用px的画postcss-pxtorem并不会帮你专程rem,就存在兼容性问题,所以上面的直接用的是rem为单位,在这个组件里我先去获取了当前设备的宽度,iphone 6/7/8 下1rem=16px;因为数据行高是34px,所以我写成了2.125rem。接下来说一下postcss-pxtorem的使用步骤吧,安装的话直接npm install postcss-pxtorem -D就行了,然后在项目了新建一个公用js文件命名为rem.js,在main.js里import到全局去
做到这我们还差一步,那就是.postcssrc.js里面还要配置postcss-pxtorem,不然也不会生效的哦。直接把'postcss-pxtorem': {
rootValue: 16,
propList: ['*']
}复制到module.exports里面就行了。
好了这个组件也讲的差不多了,如果有我讲的不够清楚的地方,没关系我把这个组件上传到我个人github了,你们可以直接clone下来跑一边,然后一步一步过代码,就会明白这个组件该怎么写了,因为是当初也是把原作者demo直接clone下来跑一遍的哈哈哈哈哈。
抛砖引玉,看出问题及不足之处的大神望指正(落魄前端,在线磕头)。