w3ctech

CSS3 Transform-3D空间变换成像原理浅析

这篇文章我将向大家简单的介绍 CSS3 里面的 3D 变换的物理成像原理,所以只是浅析,并不涉及线性代数的矩阵变换

先看一个简单的3D实例(PC端就把鼠标移上去,手机端就用手指在上面滑动,用原生JS写效果还真是...不过偶尔写写还是挺爽的):

这里本该有个示例,但是由于不能直接插入代码,可以移步到我的Blog体验:Cube-Rotate

HTML的结构:

<div class="stage three-d">
    stage
    <div class="three-d-box">
        3D-Box
        <div class="front transition">
            Front
        </div>
        <div class="back transition">
            Back
        </div>
    </div>
</div>

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变换基于几个比较重要的属性:perspectivetranslatezpreserve-3d。那么,transform 的3D变换效果是基于哪种坐标呢?每个属性又是如何控制的呢?先说一下3个属性的继承性:

  • perspective: No (http://www.w3school.com.cn 不太靠谱。。。)
  • translatez(transform): No
  • preserve-3d(transform): No
  • 补充一点:perspective虽然不具有继承性,但是它却决定了后代元素的视觉呈现。

这段代码有几个关键点元素:three-dthree-d-boxthree-d是3D变换的一个舞台元素,所有的元素都将在这里执行变换(因为它决定了所有后代元素的透视点);three-d-box则是为进行立方体变换的元素准备的一个小舞台。为什么要准备这个小舞台呢?three-d-box进行了translatez(-50px)变换,而它的子元素为么又进行translatez(-50px)变换呢?这个50px的值能换成其他值吗?先看一张GIF

3D Cube

所以我们可以看出,立方体的每个2D平面都进行着3D变换,而且都围绕着一个点,这个点就是3维坐标系的中心点,而这个点也就是three-d-box的中心点。而frontback两个子元素的变换坐标系(准确的说是相对坐标系),就是基于three-d-box的三维坐标系(所有进行2D或3D变换的元素的坐标系都是基于父元素的坐标系,父元素的中心点就是2D或3D坐标系的原点,这个原点可以根据当前元素transform-origintranslatez来改变,当然坐标是相对的,要理解这一点)。

OK,继续解决上面两个问题:设置这个小舞台的目的是为了旋转元素大小的一个可控性,直接设置three-d的大小,而且旋转元素的宽高都设置了100%,那么它们的宽高就是一样的,这样旋转元素的大小就可以通过three-d控制了。那么translatez的值呢?我就这个 Cube-Rotate 的例子说,先看一张图:

Translatez

怎么样?一目了然了吧,translatez的值就是立方体高的50%,当然这个立方体的4个侧面是一样的,这个可以根据每个面的高度的值来确定对应的translatez的值(translatez的值到底是根据旋转元素height还是width,这个也与旋转方向有关,那个GIF图不就很好的说明了吗?)。

下面在附两张我用OmniGraffle(很好用的一款思维导图绘制软件)画的两个示意图,仅供参考:

示例中的各个元素在3D空间的Z轴方向的景深示意图(1-1):

3D示意图

示例中元素在视觉系统中的成像示意图(1-2):

成像示意图

PS:上面这个图的固定视点相当于一只“机器眼”,变换元素最终呈现的客观形态就是成像到这只“机器眼”的图像,如果我们人眼的位置正好处在这只“机器眼”的位置,我们看到的是最真实的形态,当然人眼是“活动的”,成像最终取决于最终视角,和我们看现实世界的物体是一样的。固定视点的空间位置是相当于当前元素stage的,它到stage平面的垂直距离是由perspective设置的,它的投影stage平面的坐标是由perspective-origin决定的。

看了这么多理论,在线体验实践一下吧(其中还会有其他的要点):

Trandform-3D Demo created by Nokey

Nokey

w3ctech微信

扫码关注w3ctech微信公众号

共收到4条回复

  • 哇,学习了哈!

    回复此楼
  • 嘿嘿,^_^

    回复此楼
  • 学习学习,总是对3D这快晕晕的

    回复此楼
  • 分享交流哈,共同学习

    回复此楼