触屏滚动的 JS 事件处理

最近在做一个项目的时候遇到这样的问题:

一、问题描述

先上两幅图说明问题:

jsscroll-1 jsscroll-2

如是,效果是这样的,现在页面分为两个 section (#section1 & #section2),各有一个 header (#header1 & #header2);

上面那个 header 好处理,反正 fix 在顶部即可,但第二个有点麻烦:

我需要根据滚动的高度来决定第二个(下面那个《全城便民服务》)header 显示在什么地方,这会有如下三种情况:

  • Case 1: 整个显示部分都在 #section1 中,这时候 #header2 的位置应当用 fixed dock 在屏幕的底部;(图 1)
  • Case 2: 显示部分同时包含 #section1#section2,也就是说 #header2 的实际位置在屏幕显示,这时候 #header2 应该用 static 随着内容滚动;(图 2)
  • Case 3: 显示部分只包含 #section2 的内容,这时候应该 fixed dock 在屏幕顶部。(自行脑补)

二、不难想到的解决方案

ok,问题明确,现在说一下实现,反正我写了一个 js 函数,用于根据当前的滚动位置来切换这些 header 的显示:

(update_scroll = function() {
    // ... 此处省略 ...
})();

也就是说,不论何时何地,我调用一下 update_scroll 就将 #header2 的位置更新正确。

但是,用什么事件来触发是关键。

经过各种翻查,有如下两句:

$(document).on('touchmove', 'body', update_scroll);
$(window).scroll(update_scroll);

ok,在电脑上模拟很给力,以为解决。


三、麻烦之处

但是,部署到手机上测试,不是那么一回事,慢慢划还好,但是总有时候停在那里不切换。

后来慢慢重现 bug,发现在触屏上面的滚动有一个很酷炫的东西,一个字:甩!

也就是说,如果通过“甩”的方式来滚动的话,只是在你手指滑动的过程中会触发这两个时间,但是什么时候停下来,天知道。

此后各种纠结倒腾就不描述了,后来发现只有一个“变通”的办法:

在 StackOverflow 上面查找,有一个比较好的帖子:

http://stackoverflow.com/q/6359148/2544762

意思就是说,在 scroll 开始的时候先不要执行动作,歇个 100 毫秒才执行(假设甩滑的时间会在这个范围内)。

(所以关键点在于,甩滑的时间是有限的,因此只需要在 window.scroll 或者 touchmove 事件的时候延时触发一下就好,至于重复触发,其实问题不大)

然后我改进了一下,用下面这个版本,就可以把这个效果处理得比较圆滑:

$(window).scroll(function() {
    // 为了使得动作圆滑一下,我这里暴力一些,添加了多次触发,可以酌情增减。
    update_scroll();
    setTimeout(update_scroll(), 50);
    setTimeout(update_scroll(), 100);
    setTimeout(update_scroll(), 150);
    setTimeout(update_scroll(), 200);
});

That’s all.


【转载请附】愿以此功德,回向 >>

原文链接:https://www.huangwenchao.com.cn/2014/09/js-touch-scroll.html【触屏滚动的 JS 事件处理】

发表评论

电子邮件地址不会被公开。 必填项已用*标注