最近在做一个项目的时候遇到这样的问题:
一、问题描述
先上两幅图说明问题:
如是,效果是这样的,现在页面分为两个 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.
【转载请附】愿以此功德,回向 >>
原文链接:http://www.huangwenchao.com.cn/2014/09/js-touch-scroll.html【触屏滚动的 JS 事件处理】