另一页

Slider/Fullpage实现

实现思路

A.监听滚动,用JS替换元素内容。好处是渲染区域和可视区域一样大,不会浪费资源,但翻页效果不好做。

B.监听滚动,用JS控制translate变化。可视区域下,所有页面都被渲染。

遇到的问题

1.wheel事件太频繁,一次操作只应触发一次。我没有用setTimeout+clear的防抖做法,而是直接比较时间戳,属于节流。但就效果来说,两种方式都有问题。

防抖的意思是,多次频繁操作只在最后一次操作后触发一次。但Chrome(Safari已做优化)中wheel事件可能会持续接近1s,这种延迟几乎不可接受。

节流的意思是允许多次操作的第一次操作立即执行,之后一段时间都不允许再执行。这么做的后果是,1s内我都不能再划动第二次,这也不是我想要的。

我想要的效果是,初次事件立即触发,之后的事件忽略,下一次滑动时也能立即触发。

为此我做了一些优化,比如规定一个合理的忽略时间,还有,防止连续两次方向相同的滚动(因为这样很容易误判),但允许方向相反的滚动。以及forceUpdate,避免setState异步行为的延迟。

这些优化背后有一个问题,即我无法判断,在相同方向滚动两次时,究竟是上一次滚动剩下的事件,还是新的事件?不能通过滚动的程度来判断,因为用户可能轻轻一划,也可能划得很快很远。

很快,我想到了,一直以来,我用了一个React组件的一个属性来存储时间,但每个子组件都可以有自己的计时器。组件一不能连续滑动,但不影响组件二上的滑动。

举个例子,从页面1切换到页面2后,页面1在1.5s内都不会触发新事件,被视为滞后的wheel事件。但页面2可以继续滑向页面1或页面3。

分别计时虽然一定程度上区分了上一次滚动的事件和新手势的事件,但不完美。1.5s内,我有可能两次触发相同方向的滚动。

吃过晚饭,有力气思考了。我没有必要拘泥于首次之后1.5s内不触发,我可以结合防抖和节流,第一次事件发生就执行,但每次事件都会延后下一次执行的时机。

滑动效果演示:简历