一、CSS 3D 基础知识
先对 3D 基础知识进行概览讲解
再对相关属性进行详细说明
1.1 使用 transform-style 启用 3D 模式
要使用 CSS3 实现 3D 效果,主要是借助 transform-style 属性。
transform-style 只有两个值可以选择:
// 语法:
transform-style: flat|preserve-3d;
transform-style: flat; // 默认,子元素将不保留其 3D 位置
transform-style: preserve-3d; // 子元素将保留其 3D 位置
当指定一个容器的 transform-style 属性值为 preserve-3d 时,容器的后代元素便会具有 3D 效果。即当容器设置了 preserve-3d 后,它的子元素就可以相对于父元素所在的平面,进行 3D 变形操作
但仅设置
transform-style,并不能实现我们所希望看到的立体效果。为了在屏幕上看见 3D 效果的图形,还需继续设置观察者位置
1.2 利用 perspective、perspective-origin 设置 观察者 位置,实现景深效果
perspective、perspective-origin用于设置观察者位置:即从哪个位置(距离和角度)来看我们的 3D 图形
与
transform-style一样,设置于容器(父)元素上
perspective
当元素没有设置 perspective 时,所有后代元素被压缩在同一二维平面上,不存在景深的效果
而设置 perspective 后,将会看到三维效果
// 语法
perspective: number|none;
例:下图为一正方体图形,设置perspective后,出现了景深效果(正面更靠近观察者,故更大)
perspective: 400px;
perspective-origin
perspective-origin 表示观察者视角的位置
默认视角基点是 perspective 所在元素的中点,也就是 perspective-origin: 50% 50%
通过修改perspective-origin可以实现从不同角度观察 3D 图形(例如从右上角观察)
// 语法
perspective-origin: x-axis y-axis;
// x-axis : 定义该视图在 x 轴上的位置。默认值:50%
// y-axis : 定义该视图在 y 轴上的位置。默认值:50%
下图即为在 z轴正向400px处、右上方 观测到的正方体:
transform-style: preserve-3d;
perspective: 400px;
perspective-origin: 200px -100px;
二、3D 相关属性
依次阅读下文与 3D 相关的属性,将对css的 3D 坐标系有一个清晰的认识
以下图背景色 rgba(0,0,0,0.8),包含一个正方形的情况为例:
2.1 transform-style
设置于容器(父)元素上
设置元素的子元素是位于 3D 空间中还是平面中
如果选择平面,容器的子元素将不会有 3D 遮挡关系
该属性不会被继承
// 语法:
transform-style: flat|preserve-3d;
transform-style: flat; // 默认,子元素将不保留其 3D 位置
transform-style: preserve-3d; // 子元素将保留其 3D 位置
2.2 rotateX()
绕x轴旋转
x轴
轴线方向:左右横向的一条轴线(向右为正)
旋转方向:顺时针
transform: rotateX(30deg);
可见 上部分 被旋转到了平面后方
2.3 rotateY()
绕y轴旋转
y轴
轴线方向:上下竖直的一条轴线(向下为正)
旋转方向:顺时针
transform: rotateY(30deg);
可见 右侧 被旋转到了平面后方
2.4 rotateZ()
绕z轴旋转
z轴
轴线方向:垂直于屏幕(贯穿屏幕)的一条轴线(向外为正)
旋转方向:顺时针
transform: rotateZ(30deg);
2.5 translateX()
沿x轴移动
transform: translateX(30px);
注意:
css坐标系,是变化坐标系
移动后,变换坐标原点仍然在元素中心(默认);即向右移动20px,坐标系也跟着移动了20px
旋转时也是如此,元素旋转,坐标轴也一并跟着旋转
后文对
transform顺序讲解中,也有说明
2.6 translateY()
沿y轴移动
transform: translateY(30px);
2.7 translateZ()
沿z轴移动
# 注意这里设成了负数
transform: translateZ(-30px);
设为负数后,正方形移动至平面后方了
但现在不论如何改变 translateZ 正方形大小看上去并不会改变(即没有景深效果),因为我们没有设置观察者位置
想实现景深效果(即z越远,看起来越小),需要用到 perspective 属性
2.8 perspective
与
transform-style一样,设置于容器(父)元素上
指定观察者与z=0屏幕的距离,使具有三维位置变换的子元素产生透视(景深)效果
当值为0或负值时,无透视变换
三维元素在观察者后面的部分不会绘制出来
# 语法
/* Keyword value */
perspective: none;
/* <length> values */
perspective: 20px;
perspective: 3.5em;
/* Global values */
perspective: inherit;
perspective: initial;
perspective: unset;
# 示例
transform-style: preserve-3d;
perspective: 400px;
可见离观察者越近的元素,看起来越大
注意:
我们人眼在屏幕上看见的,即屏幕上显示的画面 —— 其实是元素相对于观察者,在屏幕上的的投影
详见下文【疑问: translateZ 为负数时,观察者越远,元素反而越大了?】
2.9 perspective-origin
与
transform-style一样,设置于容器(父)元素上
perspective-origin 指定了观察者的位置(类似transform-origin),默认为容器中心
下面 MDN 的示例展示了,从右下方观察 3D 正方体:
2.10 backface-visibility
设置在变化(子)元素上
backface-visibility属性定义当元素后面是否可见
# 语法
backface-visibility: visible|hidden;
以下示例为6面都透明的正方体,按正常理解,每面都透明,就可以看到后面
但如果设置 backface-visibility: hidden ,即使面的背景色为透明,也看不见其后面的元素(此时,透明度仅影响那一面的色值)
三、3D属性的一些易混淆点
3.1 translateZ 为负数时,观察者越远,元素反而越大?(元素的投影)
2.7中,对translateZ进行了介绍,它指定了元素在z轴上的移动距离
2.8对perspective进行了介绍,它设置了观察者距离z=0的距离,以实现景深效果
设想一种情况:有一 translateZ(10px) 的元素,我们移动观察者位置 perspective: 30px、perspective: 500px。那么观察者越靠近元素,元素看上去应该越大。即perspective: 30px 时,元素看上去应比 perspective: 500px 时大
事实也是如此:
但当我们将 translateZ 设为负数时,情况就发生了变化。若将 translateZ 设为负数,perspective: 30px 时,元素在屏幕上显示的大小比 perspective: 500px 时小!
这是因为,屏幕上显示(即我们肉眼看见的),其实是元素的投影
translateZ 为正时:
translateZ为正时,观察者越远,元素照在屏幕上的投影越小(屏幕上的投影才是我们人眼看见的,上图中的“眼睛”指的观察者)
所以,观察者再远,投影大小也不会小于元素本身大小
观察者非常近,投影就会无限大
观察者在元素背面,则没有投影
translateZ 为负时:
translateZ为负时,观察者越远,元素在屏幕上的投影越大!
试想,观察者就贴着屏幕,那投影就只能覆盖屏幕上1px区域
所以观察者越远,元素越大,但怎么也不会大于元素本身
观察者非常近(指非常靠近屏幕,因为观察者大于0才是有效值),元素则小到基本消失
3.2 transform 多值组合时,有顺序关系吗?
有!
transform: rotateX(180deg) translateZ(50px);
和
transform: translateZ(50px) rotateX(180deg);
不一样
css 坐标系是变化坐标系,不论元素做何变化(旋转、位移、倾斜等),坐标系也会跟着元素变化。即元素沿x移动了10px,坐标系也会跟着移动
坐标原点始终在元素中点位置(默认,其实是在transform-origin指定的位置)
而当多值组合时,从左至右执行(记住 每次执行,坐标轴也会一起变化)
以上,就是本次讲解的 CSS 3D 的所有了,让我们灵活运用吧!