之前看到过很多视差滚动的效果,例如 知乎日报App 的文章详情页,当页面滚动的时候,页面顶部图片和页面内容之间就会出现一种视觉差效果,我看到这种效果,第一反应就是监听滚动事件,然后控制图片滚动的距离与真正滚动的距离产生偏差,应该就能实现这种效果了。
确实,早期大部分视差滚动效果基本上就是如此,滚动事件是前提,然后要么是直接改变图片位置,要么如果是使用了背景图片,则改变背景图片的 background-position
,不过实际上这种方法是存在缺陷的。
监听滚动事件产生视觉差的缺陷
监听滚动事件,要想做到尽可能地流畅渲染效果,就不可以让滚动事件 节流防抖动(
Throttle debounce Immediate
),必须要时刻紧跟滚动事件才行,显然是有些耗费性能的。JS
是单线程的,存在事件轮询概念,滚动事件并不一定会立刻在滚动的每一帧执行,这取决于主线程是否繁忙,也就是说并不能保证视差滚动与页面滚动位置同步。改变一个非绝对定位元素的位置,是很有可能会触发页面的重绘,而改变
background-position
同样是会出现这种情况,比较 耗费性能,会对动画造成明显的破坏。
纯 CSS
实现
实际上,是使用 CSS3
来实现,所以 IE9
及以下就嗝屁了,而按照 caniuse 上查到的数据,IE10+
是可以用的,但我在本地模拟 IE10+
以及 Edge
都是不行的,条件有限,没有用真实版本测过,所以也不太清楚,不过如果不想管 IE9
或者 IE
,只想用在移动端的话,那就完全没关系了。
主要是 CSS3
中的 perspective
以及 translate3D
或者 translateZ
属性的应用。
一个基本的视差滚动实现如下:
// html
<div class="container">
<div class="box2">正常滚动元素</div>
<div class="box1">视觉差元素</div>
</div>
container
是滚动容器, box1
是产生视觉差的元素,box2
是正常的对照元素。
// CSS
.container {
width: 300px;
height: 400px;
overflow-y: scroll;
// 主要是下面这句
perspective: 1px;
background-color: pink;
}
.box1 {