近来有学员在群里咨询公众号排版中的视差滚动效果是如何实现的,其实这种基于纯css的视差滚动并不是什么新鲜的玩意儿,在2014年或更早国外已经有相关文章介绍过css视差滚动的实现方法,前段时间小杨@野生符号在小米手机的图文中用到了这个技术,掀起了一波视差滚动效果潮。

这次行歌就带你剖析css3d视差滚动效果的实现原理,希望可以做到抛砖引玉。

3d视差的灵魂perspective属性

我们可以用perspective属性来激活一个容器元素的3d空间特性,当一个容器设置了perspective属性后,其子元素会获得3d透视效果。

图片来源于codrops

上图中,矩形代表绘图平面,可以想象成我们的电脑屏幕,虚线的椭圆代表当前元素,蓝色区域该元素在屏幕上的投影结果。d值代表眼睛和屏幕的距离也就是perspective的值,z值代表元素和屏幕的距离。很容易发现,当z值越大,距离屏幕越远,它在屏幕上的投影就越小;反之,值越小,它在屏幕上的投影就越大,即所谓的近大远小。

通过上面的结论,我们知道觉得元素透视效果的两个因素:1.perspective值。2.元素的z值。当我们滚动容器元素时,浏览器会自动根据这些值,来自动帮我们实现近大远小的3d视差滚动效果,是不是很神奇?!

用scale值来补偿z值的副作用

刚才说过,z值会产生近大远小的效果,但这种副作用往往不是我们想要的。通常我们想要的是,即保持图片的原始大小,也能获得视差景深效果。

我们可以借助scale值来补偿z值带来的副作用,幸运的是这种补偿可以通过一个公式来计算得到,请牢记下面的公式。


scale = 1 + (translateZ * -1) / perspective

用margin值补偿位移副作用

开启3d透视后,除了对元素的大小产生副作用外,元素的位置也会根据透视产生偏移,好在我们通过设置margin值来补充这些副作用。

<section style="perspective:1px;height:600px;overflow-x:hidden;overflow-y:auto;">
  <section style="transform-style:preserve-3d;">
    <section style="transform:translateZ(-1px) scale(2);margin-top:-200px;">
      <section style="height:200px;background-color:red;"></section>
    </section>
    <section style="transform:translateZ(-2px) scale(3);margin-top:200px;">
      <section style="height:200px;background-color:yellow;"></section>
    </section>
    <section style="transform:translateZ(-3px) scale(4);margin-top:600px;">
      <section style="height:200px;background-color:blue;"></section>
    </section>
    <section style="transform:translateZ(-4px) scale(5);margin-top:1000px;">
      <section style="height:200px;background-color:green;"></section>
    </section>
    <section style="transform:translateZ(-5px) scale(6);margin-top:1400px;">
      <section style="height:200px;background-color:purple;"></section>
    </section>
  </section>
</section>

结论

通过上面的分析举例,3d视差滚动是不是很简单!你学废了没?