这篇文章我将向大家简单的介绍 CSS3 里面的 3D 变换的物理成像原理,所以只是浅析,并不涉及线性代数的矩阵变换
先看一个简单的3D实例(PC端就把鼠标移上去,手机端就用手指在上面滑动,用原生JS写效果还真是...不过偶尔写写还是挺爽的):
这里本该有个示例,但是由于不能直接插入代码,可以移步到我的Blog体验:Cube-Rotate
HTML的结构:
stage
3D-Box
Front
Back
CSS结构:
.stage{
margin: 30px auto;
width: 140px;
height: 100px;
background-color: #956129;
}
.transition{
-webkit-transition: all .3s ease-out;
-moz-transition: all .3s ease-out;
-ms-transition: all .3s ease-out;
-o-transition: all .3s ease-out;
transition: all .3s ease-out;
}
.three-d{
color: #fff;
text-align: center;
font-size: 14px;
-webkit-perspective: 200px;
-moz-perspective: 200px;
-ms-perspective: 200px;
perspective: 200px;
}
.three-d-box{
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
line-height: 100px;
text-align: center;
color: #fff;
background-color: rgba(50,50,50,.6);
-webkit-transform: translatez(-50px);
-moz-transform: translatez(-50px);
-ms-transform: translatez(-50px);
-o-transform: translatez(-50px);
transform: translatez(-50px);
-webkit-transform-style: preserve-3d;
-moz-transform-style: preserve-3d;
-ms-transform-style: preserve-3d;
transform-style: preserve-3d;
}
.front{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
line-height: 100px;
text-align: center;
color: #fff;
background-color: rgba(50,100,100,.5);
-webkit-transform: rotatex(0deg) translatez(50px);
-moz-transform: rotatex(0deg) translatez(50px);
-ms-transform: rotatex(0deg) translatez(50px);
-o-transform: rotatex(0deg) translatez(50px);
transform: rotatex(0deg) translatez(50px);
}
.back{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
line-height: 100px;
text-align: center;
color: #fff;
background-color: rgba(150,10,10,.5);
-webkit-transform: rotatex(-90deg) translatez(50px);
-moz-transform: rotatex(-90deg) translatez(50px);
-ms-transform: rotatex(-90deg) translatez(50px);
-o-transform: rotatex(-90deg) translatez(50px);
transform: rotatex(-90deg) translatez(50px);
}
一个简单的立方体旋转效果,可以移到PC浏览,console玩一下试试效果。不难看出3D变换基于几个比较重要的属性:perspective、translatez、preserve-3d。那么,transform 的3D变换效果是基于哪种坐标呢?每个属性又是如何控制的呢?先说一下3个属性的继承性:
perspective: No (http://www.w3school.com.cn 不太靠谱。。。)
translatez(transform): No
preserve-3d(transform): No
补充一点:perspective虽然不具有继承性,但是它却决定了后代元素的视觉呈现。
这段代码有几个关键点元素:three-d和three-d-box。three-d是3D变换的一个舞台元素,所有的元素都将在这里执行变换(因为它决定了所有后代元素的透视点);three-d-box则是为进行立方体变换的元素准备的一个小舞台。为什么要准备这个小舞台呢?three-d-box进行了translatez(-50px)变换,而它的子元素为么又进行translatez(-50px)变换呢?这个50px的值能换成其他值吗?先看一张GIF:
所以我们可以看出,立方体的每个2D平面都进行着3D变换,而且都围绕着一个点,这个点就是3维坐标系的中心点,而这个点也就是three-d-box的中心点。而front和back两个子元素的变换坐标系(准确的说是相对坐标系),就是基于three-d-box的三维坐标系(所有进行2D或3D变换的元素的坐标系都是基于父元素的坐标系,父元素的中心点就是2D或3D坐标系的原点,这个原点可以根据当前元素的transform-origin和translatez来改变,当然坐标是相对的,要理解这一点)。
OK,继续解决上面两个问题:设置这个小舞台的目的是为了旋转元素大小的一个可控性,直接设置three-d的大小,而且旋转元素的宽高都设置了100%,那么它们的宽高就是一样的,这样旋转元素的大小就可以通过three-d控制了。那么translatez的值呢?我就这个 Cube-Rotate 的例子说,先看一张图:
怎么样?一目了然了吧,translatez的值就是立方体高的50%,当然这个立方体的4个侧面是一样的,这个可以根据每个面的高度的值来确定对应的translatez的值(translatez的值到底是根据旋转元素的height还是width,这个也与旋转方向有关,那个GIF图不就很好的说明了吗?)。
下面在附两张我用OmniGraffle(很好用的一款思维导图绘制软件)画的两个示意图,仅供参考:
示例中的各个元素在3D空间的Z轴方向的景深示意图(1-1):
示例中元素在视觉系统中的成像示意图(1-2):
PS:上面这个图的固定视点相当于一只“机器眼”,变换元素最终呈现的客观形态就是成像到这只“机器眼”的图像,如果我们人眼的位置正好处在这只“机器眼”的位置,我们看到的是最真实的形态,当然人眼是“活动的”,成像最终取决于最终视角,和我们看现实世界的物体是一样的。固定视点的空间位置是相当于当前元素stage的,它到stage平面的垂直距离是由perspective设置的,它的投影在stage平面的坐标是由perspective-origin决定的。
看了这么多理论,在线体验实践一下吧(其中还会有其他的要点):
扫码关注w3ctech微信公众号