perspective 在前面已经介绍过,如果没有这个 perspective,网页是没有透视效果的,所谓的透视效果就是近大远小的立体效果。如果给容器设置了 perspective 属性,那么容器内的元素就会有立体效果,隔着近的就会更大,隔着远的就会更小。perspective 的属性值就可以看做视角到元素的距离。距离越近,景深效果更明显。

可以看到图中其实是平视元素的,我们其实也可以斜着看元素,需要使用 perspective-origin 属性,我们看元素都是看向元素的中心, perspective-origin 属性默认值为 center center,也就是前方就是元素中心,而我们又会看向元素中心,也就是说我们默认情况下会平视元素中心位置。我们也可以设置,比如设置为 100px 100px,那么正前方就是 100px 100px 的位置,但看元素永远是看向元素中心的,自己正前方是 100px 100px 的位置,要看向元素中心那不就得斜着去看,所以这种情况下就会斜着看元素。
我们可以很简单地演示这个 perspective 属性,前面提到过,perspective 就是透视效果,也就是近大远小。那么我们设置 perspective 之后,相当于我们眼睛距离屏幕的距离就设置好了,元素越接近我们的眼睛就会越大,元素越远离我们眼睛,就会变小,而我们的 translatez 刚好可以实现这一效果。

可以看到,如果不加 perspective ,元素离我们越近根本就不会有变大的效果。

至此,我们可以得到以下结论:
- perspective 用于设置透视效果,perspective 属性的值就是我们眼睛距离屏幕的距离
- 容器设置了 perspective 之后,容器内的元素就有了近大远小的效果,离我们越远的元素越小,离我们越近的元素越大
- 如果元素离我们的距离小于了 0,元素会跑到眼睛后面去,或者说从我们的眼睛后面消失。例如设置
perspective:800px,同时让元素沿着 z 轴移动 800 像素以上,就会跑到眼睛后面去。
我们这里多元素演示一下 perspective 和 perspective-origin

以上为四个元素,按照 y 轴旋转 45 度的效果,此时没有设置 perspective,所以毫无这种近大远小的透视效果。

此时加上了 perspective,就有了非常明显的透视效果,我们也能看到,四个盒子虽然都是旋转 45 度,但是效果是截然不同的,因为这个其实也不难理解。

从这个俯视图就能看出来,虽然这四个红色的平面的角度都是 45 度,但由于我们视角的位置的问题,每一个平面在我们眼中的显示效果也大不相同,默认情况下,我们视线的正前方都是 center center,也就是容器的中心位置。

我们通过控制台修改 perspective-origin 的值,相当于改变的我眼睛的位置,也就是我现在正前方不是盒子的正中心了,此时我看盒子就是斜着看的,也就会导致这些盒子的显示效果出现偏差。
此时我们就可以用 JS 实现一个比较炫酷的效果。
js
document.body.onmousemove = function (e) {
this.style.perspectiveOrigin = "" + e.pageX + "px " + e.pageY + "px";
}
perspective 要么为 none,要么必须是正数
以上介绍的是写在容器上的 perspective 属性,实际上还有一个 perspective 函数,这是一个 transform 的函数,如果我们在容器上写上 perspective 属性,相当于整个容器就一只眼睛,但如果我们在某个元素的 transform 属性中用上 perspective 函数,相当于这个元素就有一个单独的眼睛去看它。

此时是在容器上填上的 perspective 属性,此时整个容器就是一只眼睛,由于位置不同,所以哪怕同样是旋转 45 度,每个元素显示效果也是完全不同的。

如果我给每一个元素的 transform 属性都设置上 perspective() 函数,此时每一个盒子都有一只去看它眼睛,它们是独立的,所以哪怕是这些盒子的位置不同,最终的显示效果也是相同的。
基于上,当我们需要让一个盒子的所有元素是一个整体的透视效果,就在容器上添加 perspective,如果我只想要某一个元素按照透视效果去展示,或者我希望让每一个元素的透视效果都保持统一,那么就在这个元素上使用 perspective() 函数。
如果使用
perspective()函数,则视线正前方始终是center center,无法修改perspective-originperspective是可以叠加的,例如在容器上设置了perspective:1000px,在元素上设置了perspective(1000px),此时对于这个元素而言,其perspective的真实值就是2000px
关于 transform-style
当我们给 transform-style 属性设置为 preserve-3d,此时该元素的子元素就会变成立体渲染,如果不设置默认是 flat,也就是保持平面。如果我们要实现 3 D 效果,为了还原真实的遮盖关系,都要将这个属性加上。这个属性不会继承,需要在直接父级加。
一个元素一旦被设置上了
perspective或者transform-style,那么这个元素就会变成一个定位元素,或者说,其子元素的绝对定位会就会基于这个元素。
一般来说,我们 3 D 变换的元素结构应该如下
html
<div>
<div>
<div></div>
</div>
</div>如果读者对自己要求并不是特别高,以上内容足够应付大多数场景。
接下来深入解释一下 perspective,当我们设置了 perspective 之后,我们看到的元素就不再是元素本身,而是元素在屏幕上的投影,也就是说元素在屏幕上的投影大小,就是我们看到的大小,下面详细解释一下。

以上情况是最简单的情况,此时元素没有 z 轴的位移量是 0,也就是说直接就在屏幕上,这个元素在屏幕上的投影也就是他自己,在这种情况下,不管我 perspective 设置为多大,屏幕上的投影大小始终不会变,所以元素大小也就不会随着 perspective 改变。

此时我将元素朝着我们的视角移动,这个元素本身的大小并没有发生变化,但它在屏幕上的投影变大了,所以我们看到元素变大了。这里也能看出来为什么我说我们看到的都是元素在屏幕上的投影了,此时如果我设置 perspective,让我们眼睛离元素更近,屏幕上的投影也就会越大,显示效果也就越大。
接下来考虑另一种情况。

当我们把元素往后移动,远离我们,这里它在屏幕上的投影就变小了这个也是我们能够理解的情况。最后看一种情况,就是在这个基础上,我们移动视角,而不移动元素。

我们会发现,随着视角离着屏幕越来越近,元素在屏幕上的投影反而越来越小了,这就是一个很反直觉的问题了,如果按照近大远小的思路分析,不管在什么情况下,元素离我们眼睛距离越远就应该越小,距离越近就应该越大对吧,但是如果元素是在屏幕里面,或者说 z 轴的位移量为负数,那么随着我们视角的靠近,元素在屏幕上的投影反而越来越小,也就会显示地越小。