
透视:由平面向空间过渡的桥梁
CSS3 3D 变换的本质不是去画一个三维物体,而是用一种方式来表现人在三维空间中看到的景象。浏览器把 DOM 元素当作一张纸来处理,使用透视投影矩阵把它转换成二维画面。
perspective 属性用来定义观察者和 z=0 平面之间的距离(单位:px),这个数值越小,则透视效果越明显;反之则越接近于正交投影的效果。如果没有设置 perspective 的话,所有的三维变换都会变成二维平面的缩放。
.container {
perspective: 1000px; /* 观察者距离 */
perspective-origin: 50% 50%; /* 消失点位置 */
}
变换函数:三维空间里六种基本的运算
CSS3中有两种三维变换函数:位移和旋转,还有复合的matrix3d。
关键细节:translateZ 正值使元素向观察者靠近,视觉上放大;负值远离,视觉缩小。该效果与 perspective 值共同决定放大比例。
改变原点和渲染环境
transform-origin 默认为 50% 50% 0,可以接受一个第三参数来设置 Z 轴上的偏移量。如果元素要围绕某个非中心点进行旋转的话,那么这个属性就用来确定旋转轴的位置了。
.card {
transform-origin: bottom center -50px;
transform: rotateX(20deg);
}
transform-style: preserve-3d 是创建嵌套的3D场景所必需的一个属性,它的默认值是flat,即子元素的3D变换会被扁平化到父级平面上去。当它被设置为preserve-3d时,则子元素会保持自己独立的三维空间关系,可以构成立方体、折叠面板等复杂的结构。
.scene {
transform-style: preserve-3d;
}
.face {
position: absolute;
backface-visibility: hidden; /* 隐藏背面 */
}
backface-visibility 用来决定元素背面是否可以被看到,设置为 hidden 的话,在元素转动到90度以上的时候会自动隐藏起来,一般用于制作翻牌或者3D相册这样的效果。
透视矩阵和浏览器的渲染管道
浏览器把3D变换分成以下几个步骤:
-
构建变换矩阵:根据
perspective、rotate、translate等属性计算 4×4 齐次坐标矩阵 -
顶点变换:将元素四个角点乘以矩阵,得到投影后的二维坐标
-
深度排序:根据
translateZ值对元素进行隐式深度排序(不触发重排) -
光栅化:按深度从后向前绘制,处理层叠上下文
性能陷阱:频繁修改 perspective 或 transform 会触发复合层更新,但不会触发重排。推荐使用 will-change: transform 提前提升为独立合成层。
.animate-3d {
will-change: transform;
transition: transform 0.6s cubic-bezier(0.4, 0.0, 0.2, 1);
}
实践:建立可以互动的三维立方体
下面是一个可以拖动并旋转的立方体:
<div class="scene">
<div class="cube">
<div class="face front">1</div>
<div class="face back">2</div>
<div class="face right">3</div>
<div class="face left">4</div>
<div class="face top">5</div>
<div class="face bottom">6</div>
</div>
</div>
.scene {
width: 200px;
height: 200px;
perspective: 800px;
}
.cube {
width: 100%;
height: 100%;
position: relative;
transform-style: preserve-3d;
transition: transform 0.8s;
}
.face {
position: absolute;
width: 200px;
height: 200px;
display: flex;
align-items: center;
justify-content: center;
font-size: 48px;
background: rgba(0, 150, 255, 0.8);
border: 2px solid #fff;
}
.front { transform: translateZ(100px); }
.back { transform: rotateY(180deg) translateZ(100px); }
.right { transform: rotateY(90deg) translateZ(100px); }
.left { transform: rotateY(-90deg) translateZ(100px); }
.top { transform: rotateX(90deg) translateZ(100px); }
.bottom { transform: rotateX(-90deg) translateZ(100px); }
let isDown = false, lastX, lastY, rotateX = -20, rotateY = 30;
document.querySelector('.scene').addEventListener('mousedown', e => {
isDown = true; lastX = e.clientX; lastY = e.clientY;
});
document.addEventListener('mousemove', e => {
if (!isDown) return;
rotateY += (e.clientX - lastX) * 0.5;
rotateX -= (e.clientY - lastY) * 0.5;
document.querySelector('.cube').style.transform =
`rotateX(${rotateX}deg) rotateY(${rotateY}deg)`;
lastX = e.clientX; lastY = e.clientY;
});
document.addEventListener('mouseup', () => isDown = false);
性能优化和兼容性的策略
-
硬件加速:3D 变换自动启用 GPU 加速,但过度使用
preserve-3d会增加合成层数量,消耗显存 -
锯齿处理:旋转元素边缘出现锯齿时,添加
outline: 1px solid transparent或backface-visibility: hidden强制创建新图层 -
移动端适配:iOS Safari 对
perspective支持良好,但transform-style: preserve-3d在部分版本存在渲染 bug,需添加-webkit-前缀并测试 -
降级方案:通过
@supports (transform-style: preserve-3d)检测支持性,不支持时回退到 2D 变换或 JavaScript 动画库
高级应用
-
视差滚动:多层元素设置不同
translateZ值,配合滚动事件实现深度视差 -
卡片翻转:
rotateY(180deg)配合backface-visibility实现信息正反面切换 -
全景查看器:通过
rotateY映射鼠标水平位置,模拟 360 度环视 -
数据可视化:3D 柱状图、散点图利用深度轴表达第三维度数据
-
游戏界面:卡牌游戏中的发牌动画、角色选择界面的 3D 轮播
总结
CSS3 3D 变换利用透视投影来模拟三维空间,主要依靠 perspective 来设定观察距离以及 transform-style 来控制渲染上下文。合理的位移和旋转函数可以构成立方体、折叠面板等复杂的结构。性能优化要考虑合成层数量以及硬件加速边界的问题,在移动设备上要进行专门的测试。要理解透视原理和矩阵变换逻辑,在没有 JavaScript 的情况下也可以做出沉浸式的三维交互效果,给界面设计提供了新的表达方式。






