React中实现循环滑动效果难点
最近有这样一个需求,在h5页面上,向左/向右滑动循环显示数据项,效果如下:
比如有3个页面,从第一个页面向左滑动到第二个页面,或者从第二个页面向左滑动到第三个页面,很简单,只需要将left从0%切换到-100%,或从-100%更换到-200%,然后在对left增加transition属性,如:transition: left 0.5s
,就可以简单实现从第一张滑动到第二张,第二张到第三张,那么从第三个页面如何继续向左滑动到第一个页面,如果仅仅将left从-200%直接更换到0%,那么视觉上的效果就是从最后一页像右滑动到了第一页,滑动效果就变了,如下:
那么如何让从最后一张也保持不变的滑动效果滑动到第一张呢?
从最后一张直接改变属性到第一个页面是不太可能实现该效果了,要实现向左滑动,那么动画的left属性还是得变的越来越小,如-100%--> -200%
,为了实现这个效果,我们可增加一个过渡页面,该过渡页面可与第一个页面一样,就是第一个页面的clone页面,作为第4个页面,即第当从第三个页面滑动到第一个页面的时候,实际上滑动到的是该过渡页面(第4个页面),再当从第4个页面继续向左滑动的时候,那么应该滑动到第2个页面,这时可先设置setState({left:0})
(render页面的时候并没有变化,由于当前的第4个页面就是第一个页面的clone),在该setState
的callback
中再设置left: -100%
,这时left的属性就是从0–>-100%,即实现了向左滑动的效果的条件。
代码如下:
1 |
|
但是另一个问题又来了,为何setState left:0
好像没起作用, 浏览器直接从当前状态直接过度到了setState callback
中的状态?
原来是由于在一个渲染帧中,浏览器会忽略中间的状态,直接渲染最后一个状态,所以其中的left:0
效果会没有了,如A->B->C, B和C在一个渲染帧中,那么我们将直接看见从A->C的变化状态,而忽略B的状态,从根本上的解决该问题就是让这2个状态在2个渲染帧中,解决方法有如下:
1.将C的状态放在setTimeout中,最好timeout时间超过16.7ms(1/60),如果timeout设为0,在某些浏览器可能不工作
1
2
3setTimeout(() => {
this.setState({outerStyle: this.outerStyle});
}, 20);
2.采用requestAnimationFrame
1 |
|
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!