文章目录

  • 前言
  • 阻尼效果
  • 实现思路
  • 尝试方案一
  • 优化思路
  • 三层双滑动窗口模型
  • 结语


前言

不知道大家是否知道阻尼效果,这个效果只能在移动端才能实现,因为它的本质是touch事件以及scroll事件的某些行为。
相信大家应该都用过知乎吧,在知乎里两个页面之间就有一个阻尼层。(大家可以打开手机知乎体验一下)

阻尼效果

那么究竟阻尼效果是什么呢?
简单来说,就是界面滑动到了最底部或最顶部仍可以比实际的内容多滑动一段距离然后回弹的弹性效果,并且在页面的其它地方操作时依旧是非常流畅的滚动效果。

实现思路

既然知道了目标效果,那接下不妨想想该如何进行实现。

尝试方案一

一个非常直接的思路是将所有页面进行平铺,并监听阻尼标识在当前视窗的位置,一旦当阻尼满足了距离条件,就立马阻止掉页面的滚动行为并允许touch行为。
那么此时的页面结构就类似于这样:

<div id="box">
        <div class="page1"></div>
        <div class="damp">阻尼</div>
        <div class="page2"></div>
        <div class="damp">阻尼</div>
        <div class="page3"></div>
</div>

但是,尝试过后我们会发现,理想是美好的,现实却是残酷的。由于移动端滚动条的特殊机制,我们无法控制并立马禁止其默认的滚动行为。我们可以使用box.scrollTop让其强行定住,但是显然它还是会产生很明显的抖动现象。所以此方案得进行优化。

优化思路

那么是不是就真的没有办法处理这个问题的吗?显然肯定不是,比较人家知乎也没见着会抖动啊,再打开知乎去体验一下人家的阻尼效果,细心的我们会发现它的滚动条的长度会变化,并且它之所以不会产生抖动的本质是因为它当前的页面就只有那么高
滚动只有那么高确实就不会出现阻尼抖动的问题,但是那么它又是如何滑动下一个页面的内容的呢?
那么接下来就是见证奇迹的时候

三层双滑动窗口模型

首先,我先给出这个模型的dom结构:

<style>
        #window-out {
            height: 500px;
            overflow: scroll;
        }
        #window-in {
            overflow: hidden;
        }
</style>
<div id="window-out">
        <div id="window-in">
            <div class="page1"></div>
            <div class="damp">阻尼</div>
            <div class="page2"></div>
            <div class="damp">阻尼</div>
            <div class="page3"></div>
        </div>
</div>

下面我就基于此模型来给大家逐一解决上面的困境:

  1. 三层分别代表:外窗口out层,内窗口in层以及平铺的页面层。
  2. out层为可视区域的大小,它能滚动的区域是window-in的大小。
  3. in层为中间层,它能滑动的区域是整个平铺页面的大小。
  4. in层的出现首先避免了滚动条的抖动现象,并且通过改变in层的scrolltop能够滑动看到下一页的内容。

至于知乎页面头部的滑动效果其实也很简单,通过transform改变in层的translateY即可。
这里可以顺便给大家补充一个小细节:
显示下一页的内容只能通过改变scrolltop,改变translateY超出部分会显示其父元素的内容(out层)。

结语

授人以鱼不如授人以渔,这一次我就不给大家展示完整案例的demo代码,因为我觉得这个功能的难点在于设计思路,如今思路已经明了,剩下的无非是照着思路写代码。老规矩,如果大家对于此思路有任何疑问或者确实写不出代码,可以评论区留言或者私聊我,我会积极给予答复。那么,下期再会。