然后接下来,这事还没完,还有一个问题。
比如说有很多手机上的 App 和网页,它往往都有一个功能。
就是说,中间的内容可以上下拖,是正常的,但是我们能把它拖过头吗,就像下面这样:
其实有些是可以的,但是一般来讲,我们这种可能会常见于下拉刷新一系列的。
但是大家可以拿出手机试试,比如你拖动某个页面,当你拖过了,它还是走的那么快吗?
是不是你可以感觉到当你拖过去了以后,它走的就会变慢一些。
所以说在这种情况下,如果我们想要去完成这样的一个效果,其实非常的简单。
我们可以先把 y 给打印出来,你可以看到,事情是这样的。
当我们往上拖的时候,y 是负的:
而当我们拖到这的时候,y是正的:
所以我们就可以通过这个 y 是正还是负,来判断这个事。
那么如果 y > 0,我们可以乘等于 0.3:
那么现在我们可以试试,如果往上拖,是没有问题的。
但是我们一旦往下拖的时候,你会发现,拖了很多,但是它才走了一点:
当然有人说,这个速度的值是多少不一定,万一用户想自己定呢?没问题,这个是可以的。
比如我们现在有一个默认的系数 factor,是 0.3:
那么下面的 _doMove 里边,我们就可以乘等于这个系数:
那么这个就算是出来的。
以及还没完,比如我们现在往上拖,拖过了:
那这时候,我们是不是也得处理一下。
那我最大能拖到哪,怎么算?是不是里面的高,减去外面的高。
所以我们还需要一个值,就直接来了:
当然这时候有一个小问题。
那有没有可能里面的高就只有一小块,比外面的小?
其实是有可能的,所以我们需要判断一下。
如果外面的高,小于等于里面的高,这个其实算是相对来说正常的一种方式,那么我们的 maxY 就等于里面减外面的:
而如果外面的高,大于里面的高,那么就是这样的情况:
那么我们这个 macY,其实它最多只能拖到 0。
因为里面那个红框,它在没动的情况下,就已经和底下脱节了,在动就更过了,所以它是 0:
那么我们还需要一个maxX,因为横向和纵向是完全相同的两个东西。
并且,如果 x > 0,其实也是一样的。
并且,因为 y 是负的,越往上越小,而 maxY 是正的,所以如果 y < -maxY,那么这时候怎么办呢?
那么我们能直接乘吗?其实不能,为什么?
比如说我现在往上拖过了:
其实我现在只应该对下面的这一段来乘我那个系数:
为什么呢?
因为说白了,它上面那一段,你还是照样来用的。
举一个不太靠谱,但是很恰当的例子,个人所得税是分阶算的。
比如说 5000 块以下的不用交,如果超过 5000,比如说你 6500,那你只用交那 1500 的税就可以了。
所以在这种情况下,我们只用对它超出的那部分来算就行:
为什么是 y + maxY 呢?因为 y 是负的,maxY 是正的,所以一负一正相加就是一个相减的关系,然后我们乘以系数。
并且还要再加上那一段 maxY:
因为这一段是没有税的,最后再赋值给 y 就可以了:
那么现在我们再往上拖,当它过了之后,就又慢了:
这个就是我们要的效果。
那么我们的 x 也是一样的:
然后这事还没完,还有一个小问题。
就是说我们在现在这个位置,如果松手了之后,它就一直呆在这吗?
不是的,它是不是应该弹出去,回到 0 啊?
所以我们应该在 _doEnd 的时候,加上这个判断,x、y 都是一样的:
以及还有另一个,最大值的问题。
如果它已经超出了,我就让它等于那个最大值。
当然,我们直接把 maxX 和 maxY 的计算,从 _doMove 里边复制下来:
然后,如果现在的 x < -maxX,说明我们超了,那这时候 x 就等于 -maxX,最大就到这,多了不能有,y 也是一样的:
那么现在还有一个小问题,我们现在怎么让它回去?
最简单的方法肯定是这样的:
然后我们来看看效果:
可以看到,下拉,松手,是能回来的,但是是瞬间回来。
虽然这样能达到效果,但是这个太僵硬了。
那么我们可以加一个 transition:
那么这个 300 ms 是定死的吗?
我们是不是可以把它也作为一个默认的参数?
以及,有人规定一定是 all 吗?万一有其他的呢?
所以我们可以只负责 transform:
以及,有人规定一定是 ease 吗?
我们是不是也可以加一个默认的参数:
那么现在我们再来试试:
就可以看到,松手的时候,它是慢慢弹的回去了。
这时候还没完,如果大家做过类似 transition 的东西就一定会知道。
比如现在第一次拖完之后,没问题,是可以慢慢的回去。
但是之后,我们拖完第一次,第二次在拖的话,就会特别卡。
为什么会卡呢?
原因非常的简单,因为我们加上 transition 了之后,那么你以后所有的对 transform 的修改,都会以动画的形式呈现。
那么这时候就有一个问题,我们下次再 move 的时候,是不是也要改 transform?那这时候就挂了。
所以这事怎么解决,非常的简单。
我们可以在 _doStart 的时候,让它变成空的:
所以现在我们第二次再拖的时候,就会很顺畅了。
然后接下来,这事还没彻底完,我们现在作为一个简单的拖拽库,也许是凑合。
但是如果我们现在做到这就完了,其实用起来是非常不方便的。
因为像这种东西,我们是经常需要去跟 js 去配合的。
比方说,我希望当它拖拽的时候,你得告诉我现在拖到哪了,拖了多少等等一系列的事。
比如现在,我在参数里面加一个 move 函数:
这个名字叫啥都行,因为库是我们自己写的,爱叫什么都可以。
我们加这个 move 的原因非常的简单,就是为了一件事,我可以监听你的移动。
所以在这个时候,在 _doMove 里面,我需要去检查,并且触发一下用户的 move 函数。
也就是说,我要看下 options 里面有没有 move,然后还要看看它是不是一个 function:
然后接下来,如果都 OK 的话,那我就执行它一下,并且执行的时候,我把坐标给你:
那么我们先来试试:
可以看到是可以的,当我们拖动的时候,x、y 都是有的,没有问题。
那么能有 move,我们是不是还能有 start 和 end:
那么我们在来试试:
到此,我们就实现了一个最简单的滚动库。