Quantcast
Channel: w3cplus
Viewing all articles
Browse latest Browse all 1557

[转载]玩轉 CSS 3D: 原理篇

$
0
0

本文转载于@oxxo的玩转CSS 3D系列教程第一篇:http://www.oxxostudio.tw/articles/201506/css-3d.html

這篇 CSS 3D 的文章,其实酝酿已久,从CSS 3D 出来的时候就已经在关注,只是要写 CSS 3D 真的很费工,里面有太多东西要讲,加上最近在做 Webduino 可以改变世界的事业 ( Webduino 超赞呀! ),所以就一直搁着了,趁着端午放假,一口气把它搞定吧!

虽然 CSS 3D 并非真的 3D,CSS 3D 坦白说就是纯粹利用计算的方法,借着浏览器的高效性能,在 2D 的空間绘制一个 3D 的图形,就像我们拿张约,用铅笔在上头画个正立方体之类的,也因为是借了浏览器的运算,自然而然非常地耗性能,往往只要有过多的形状转换为 3D 呈现,就会发现电脑的风扇开始狂转,这也是使用 CSS 3D 必须要注意的地方,毕竟 CSS 原本就不是拿来做 3D 应用的技术,可以画 3D,只是可以加强 CSS 呈现的美感和能力,但用在精细的 3D 动画或转场效果,还是交给专业的 3D 绘图软件来运行。

从这篇开始以及再来的一两篇,将会深入介绍 CSS 3D 的绘图以及直接做些应用,如果你已经会了 CSS 3D,不妨也可以看看正多面体该如何制作,可以参考這两篇:玩转 CSS 3D - 正四面体与正六面体玩转 CSS 3D - 正八面体与正十二面体

3D手式

我们这边先来用 Google SketchUp 这个免费的 3D 建模软件,看一下最普通的 3D 绘图的介面,里头最基本的会有三个元素,第一个:摄影镜头,第二个:立体空间,第三个:立体物件。

CSS 3D

摄影镜头主要定义了观看者的角度,就如同我们在拍照,使用长焦距的望远镜头,物体可以拉近且不会变形,使用短焦距的广角镜,拍摄的物体就容易变形,从下图可以看出,镜头的焦距可以让空间內的物体产生不同的变形,至于立体空间则是具备了 XYZ三个座标轴的空间,立体物件则是在这个空间里头的物件。

CSS 3D

所以绘制 CSS 的 3D 图形,最重要的也就是要架设这三个物件,不过因为在 CSS 里並沒有摄影镜头、立体空間...等。這些 3D 软件才有的元素,所以变成都是用 div取代,在对应的 div上头加入对应的 style 属性,就可以进行模拟,运用上面所提到的三个元素,我们这里就必须要用到三层div,最外层是摄影镜头,第二层为立体空间,第三层是是立体空间內的立体元素,写出來的 HTML 长得就像下面这样:

<div class="camera">
    <div class="space">
        <div class="box"></div>
    </div>
</div>

设定 camera

接着就要来把最外层的 div ( 以下通称 camera ) 设定为摄影镜头,设定的方法为添加 perspective-origin以及 perspective这两个属性,这个属性是什么呢?简单来说就是透视点以及镜头到透视点的距离,如果直接查询 perspective,看到的八九不离十是下面这些图案:

CSS 3D

然而在 W3C 里头对于 perspective的解释则是下图这样,透视点同样也是物体到摄影机的距离 ( d ) ,但又因为 CSS 的 3D 空间里头具有 Z轴,所以 perspective的距离会因为 Z轴的关系而有所缩放 ( 不过千万要注意,这里的 Z指的是物体的 Z轴,也就是 translateZ,不是摄影机的 )。

CSS 3D

此外,perspective-origin是摄影机的中心点位置,预设相对应空间 div ( 以下都称为 space ) 的中心点,不做设定的话,预设都是 center center ( 或 50% 50% ),换句话说,作为摄影镜头的 camera 的三個维度,perspective-origin代表了 XY轴,而 perspective代表 Z轴 ( 和內容物体的 Z轴相减才会变成摄影机的 ),camera 就可以在三维空间里头进行移动,下图同样是 W3C 对于 perspective-origin所作的解释,当摄影镜头往上,图形的下半部就看不到了。

CSS 3D

回到 CSS 来看的话,我们可以像下面這样设定,这时候画面完全不是正常的,因为还沒有设定空间和物体。

.camera{
    width:200px;
    height:200px;
    perspective-origin:center center;
    perspective:500px;
}

设定 space

摄影机完成后,就是要设定一个立体空间 space,这个空间设定的方式很简单,只要设定一个属性:transform-style,这个属性预设为 flat,也就是只要是這个 div內的子元素,一律都是以扁平 ( flat ) 的方式呈现,所属的变换 transform也一律都是用 flat的方式变换,换句话说就是沒有 Z轴的存在,为了让內容元素都是立体元素,所以我们要將 transform-style设为 3D,如此一来內容元素就全部都可以用 3D 进行变换,为了方便区分,下面我将 space 外围多加一个 boder做区别。

.space{
    width:100%;
    height:100%;
    border:1px dashed #000;
    transform-style:3d;
}

CSS 3D

设定 box

最后就是內容元素 box 了,我们可以添加一个 100px x 100px的 box 进去,接着,用这个 box 来复习一下前面讲的观念,在沒有设定 box 的 traslateZrotate的情形下,不论我们如何去修改 camera 的 perspective-originperspective,box 的大小和位置都不会有变化,为什么呢?因为在沒有设定 box 的 translateZrotate,让 Z的深度有所变化,摄影机透过 perspective看出去的位置都是相同的,也造成不论怎么去看这个 box 都是一样的大小。

.box{ width:100px; height:100px; background:#069; transform:translateX(50px) translateY(50px); }

CSS 3D

不过当我们给 box 改变 Z轴的深度之后 ( 这里我先把 translateZ设定为 150px ),再去改变 camera 的 perspective-originperspective,一切彷佛就有了变化。

.box{
    width:100px;
    height:100px;
    background:#069;
    transform:translateX(50px) translateY(50px) translateZ(150px);
    translateZ(150px);
    translateZ(150px);
}

CSS 3D

大概了解之后,来把 box 旋转一下角度,看得应该就会更清楚,当摄影机变成广角,也就是 perspective变短,整个旋转后变形也会更加明显,大家可以用开发者工具修改 camera 的 perspective就会明白。

.box{
    width:100px;
    height:100px;
    background:#069;
    transform:translateX(50px) translateY(50px) rotateY(60deg);
}

CSS 3D

改变一下 perspective-origin也会很有意思。

CSS 3D

我们加入多一点的 box,并且让这些 box 的位置改变或旋转,看看效果如何,这里比较需要注意的地方,是我们必须要额外在每个 box 加入 position:absolute的属性,因为 div本身为 block 属性,会互相挤压,要设定位置为绝对位置,才会正确地放在 space 里头。

.space div{
    position:absolute;
    width:100px;
    height:100px;
}
.box1{
    background:#069;
    transform:translateX(50px) translateY(50px) rotateY(60deg);
}
.box2{
    background:#c00;
    transform:translateX(100px) translateY(20px) rotateX(60deg);
}
.box3{
    background:#f90;
    transform:translateX(0px) translateZ(-250px) rotateY(20deg);
}
.box4{
    background:#0c9;
    transform:translateX(20px) translateY(80px) rotateX(-80deg);
}

CSS 3D

正如上述的三个 3D 元素,我们就可以轻松的绘制 CSS 3D 图形,不过除了 camera、space 和 box 之外,还有一个最重要最重要最重要的撰写規律在里头 ( 因为很重要所以要说三次 ),这个規律就是 tramsform里头是有順序的,因为 CSS 3D 完全是由 2D 演算而来,并不是真的像 3D 软件是真的有 3D 的空间,所以就变成会「按照順序」进行演算,而且又因为 transform会造成物体的整个座标轴变换,在順序的编排上就格外重要。

例如今天我先让 box 在 X轴上水平位移 100px再绕着 Y轴順时针转 60度,和先绕 Y轴順时针转 60度,再在 X轴上头水平位移 100px的结果会完全不同,因为当我先绕了 Y轴转动,整个 X轴也会跟著转动,这时候再做水平位移,位置就会像是在深度做变换。

.space div{
    position:absolute;
    width:100px;
    height:100px;
}
.box1{
    background:#069;
    transform:translateY(50px) translateX(100px) rotateY(60deg);
}
.box2{
    background:#c00;
    transform:translateY(50px) rotateY(60deg) translateX(100px);
}

CSS 3D

transform的数量少还比较看不出來,当今天 transform里头数量一多,造成的差异就更加明显,这也是在玩 CSS 3D 最最最最最需要注意的重点所在,一定要注意,一定要注意,一定要注意,非常重要所以再说三次呀!

.space div{
    position:absolute;
    width:100px;
    height:100px;
}
.box1{
    background:#069;
    transform:translateY(50px) translateX(100px) rotateY(60deg) rotateX(60deg) translateX(-50px);
}
.box2{
    background:#c00;
    transform:translateX(-50px) translateY(50px) rotateX(60deg) rotateY(60deg) translateX(100px);
}

CSS 3D

以上就是 CSS 3D 的原理解析,坦白说如果明白了 3D 的结构组成,CSS 的 3D 就沒有难度,总而言之,就是先建立好三個元素:摄影机、立体空间、立体物件,就可以开始玩转 CSS 3D 啰!

本文转载于@oxxo的玩转CSS 3D系列教程第一篇:http://www.oxxostudio.tw/articles/201506/css-3d.html


Viewing all articles
Browse latest Browse all 1557

Trending Articles