前情提要:本篇文章已经默认你已经彻底了解perspective和translateZ的含义与用法,如果尚未了解,我推荐你看css3系列之详解perspective
Part1 什么是视差滚动?
如图所示,紫div和红div的滚动速度是不同的,比如用户滚动了300px,但红div按1:2,只滚动了150px,而紫色div按1:1,滚动了300px。
最终形成了多个div滚动距离不一致,体现了"视差"的效果,简单的来说,就是视差滚动,它的原理就是滚动速度不一致!
你问这有什么用?
那么你可以尝试访问这个网站
http://www.firewatchgame.com/
是不是比起普通网站多了一层酷炫?想知道如何实现吗?接下来我们进入part2。
Part2 视差滚动的实现
步骤:
1.建立一个容器元素,设置 overflow-y: scroll 使其可以滚动(同时可能需要 overflow-x: hidden)。
2.对于上面的元素, 我们会应用一个 perspective 值,然后设置 perspective-origin 到 top left, 或者 0 0。
3.对上面元素的子元素应用一个在 Z 轴的变换,然后把它们还原回来以实现视差效果,而没有影响它们在屏幕上的大小。
这种方案下的css和html:
.container {
width: 100%;
height: 100%;
overflow-x: hidden;
overflow-y: scroll;
perspective: 1px;
}
.parallax-child {
transform: translateZ(-2px) scale(3);
}
是不是很简单?
<div class="container”>
<div class="parallax-child”></div>
</div>
现在的你已经写出基本的视差滚动动画了!但是perspective和translateZ是怎么影响滚动速度的?还有scale,为什么这里设置的是3?想知道吗?那么接下来进入part3
Part 3 原理解析
这里把scale设为S,pespcetive->P,translateZ->D //注意D一般是负值
那么有公式S=(P-D)/P,
这个公式怎么来的?这其实就是一个简单的相似三角形
划红线的地方的比例就是1:3,那么你只需要在原来的基础上放大3就可以让图形变回原来的比例,这里的1就是P,2就是D,那么很容易发现图形的缩小比例是P/(P-D),想放大回来?倒置这个缩小比例即可,我们便得到了S=(P-D)/P
现在我们已经靠scale属性让图形变回了原来的大小,似乎一切都恢复了原状,但有一个东西,它变了,便是滚动速度,滚动速度和上面的缩小比例是完全一致的,以如下数据为例
父元素
perspective: 1px;
子元素
transform: translateZ(-2px) scale(3);
不看scale,这里的缩小比例是1/3,那么由于css机制,它的滚动速度也会变成原来的1/3。即使添加了scale属性,它的滚动速度依然不变还是原来的1/3。
现在让我们来总结性质:
父元素设置perspective,子元素设置 translateZ(-2px),那么无论是否有scale属性,
则有
缩小比例=滚动速度比=P/(P-D)
PS:如果不设置 translateZ,或者 translateZ(0),那么对应D=0,所以有缩小比例=滚动速度比=(P/P-0)=1:1,即相对于原来的滚动速率不变。
为了方便读者尝试,我码了一个小小的demo,你可以任意更改属性来验证上面的结论!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<style>
html,
body {
margin: 0;
font-family: Helvetica, "PingFang SC",
"Microsoft Yahei", sans-serif;
background:#00b894;
display: flex;
justify-content: center;
align-items:center;
height:100vh;
}
* {
box-sizing: border-box;
}
.container {
width: 50vh;
height: 50vh;
overflow-x: hidden;
overflow-y: scroll;
perspective: 1px;
}
.parallax-child {
width:50vh;
height:50vh;
border:1px solid black;
/* transform-origin: 0 0; */
transform: translateZ(-2px) scale(3);
background:rgba(255,255,255,0.5)
}
.another{
width:50vh;
height:50vh;
border:1px solid black;
background:rgba(0,0,0,0.5)
}
</style>
</head>
<body>
<div class="container">
<div class="parallax-child"></div>
<div class="another">2333333333333333</div>
</div>
</body>
</html>
参考:
Performant Parallaxing :https://developers.google.com/web/updates/2016/12/performant-parallaxing
[杨耿]css3系列之详解perspective:
https://www.cnblogs.com/yanggeng/p/11285856.html