上周簡單寫了一下2D變換
今天來寫寫3D變換
三維立體效果我覺得是CSS3中最有意思的地方
不得不佩服那些開發人員大神們
讓我們能夠通過幾行CSS代碼就能得到酷炫的視覺體驗
瀏覽器座標系
在講正式文法之前,首先需要瞭解瀏覽器座標系
這需要我們把瀏覽器介面想象成一個立體的情境
這是網上流傳很廣的瀏覽器座標系圖片
從左至右的方向是瀏覽器x軸的正方向
從上到下的方向是瀏覽器y軸的正方向
而z軸正方向是面對於我們的
瞭解這個很重要,因為下面我們旋轉元素需要藉助它來理解
3D旋轉
我們在平面中使用的旋轉只是單純的讓元素在平面旋轉一定角度
在三維旋轉中稍微要複雜一下
屬性當然還是用我們的transform
三維旋轉有下面三個函數分別對應三個維度旋轉
rotateX(xxdeg)
rotateY(xxdeg)
rotateZ(xxdeg)
rotateX是讓元素繞著x軸旋轉,角度越大,元素繞著x軸順時針旋轉
類似於我們的單杠運動
transform: rotateX(45deg);
rotateY是讓元素繞著y軸旋轉,角度越大,元素繞著y軸順時針旋轉
類似於鋼管舞運動..
transform: rotateY(45deg);
rotateZ是讓元素繞著z軸旋轉,角度越大,元素繞著z軸順時針旋轉
這就是我們在二維平面的旋轉,類似於轉盤
transform: rotateZ(45deg);
其實3D旋轉還有一個合成的函數是rotate3d(num,num,num,deg)
用的不是很多,我就簡單說一下
參數並不是我們想那樣的3個角度值
而是三個數字一個角度值
前三個數字分別表示繞x、y、z軸旋轉的向量值
最後一個表示在空間的旋轉角度,等價關係如下
rotate3d(1,0,0,xxdeg) <==> rotateX(xxdeg) rotate3d(0,1,0,xxdeg) <==> rotateY(xxdeg) rotate3d(0,0,1,xxdeg) <==> rotateZ(xxdeg)
3D位移與3D縮放
我們在2D中用到translateX()和translateY()在平面移動
3D中我們多了translateZ()允許我們沿著z軸平移
同樣可以使用合成函數translate3d(x,y,z)
注意前兩個值可以使用百分比形式,但是沿z軸平移的值只能使用長度值
同理我們的3D縮放
scaleX(num)、scaleY(num)、scaleZ(num)、scale3d(num,num,num)
至於它們的用法下面再通過例子來說
(3D的傾斜屬性是不存在的,換句話說,不存在skew3d函數)
透視/景深屬性perspective
景深這個名詞,維基百科是這樣就解釋的
景深(英語:Depth of field, DOF)景深是指相機對焦點前後相對清晰的成像範圍。在光學中,尤其是錄影或是攝影,是一個描述在空間中,可以清楚成像的距離範圍。雖然透鏡只能夠將光聚到某一固定的距離,遠離此點則會逐漸模糊,但是在某一段特定的距離內,影像模糊的程度是肉眼無法察覺的,這段距離稱之為景深。當焦點設在超焦距處時,景深會從超焦距的一半延伸到無限遠,對一個固定的光圈值來說,這是最大的景深。
(看到這裡,我的手默默的離開了鍵盤,仰天長歎,心想,這到底要什麼樣的學曆才能看得懂)
我們可以這樣來理解
景深就是我們的肉眼距離顯示器的距離
景深越大,元素離我們越遠,效果就不好
在我們CSS3中,perspective用於啟用一個3D空間
屬性值就是景深大小(預設none無景深)
有兩種用法
.stage { perspective: 500px;}
應用景深的元素稱為“舞台元素”
舞台元素的所有後代元素都會受影響
(如果後代元素中也添加了perspective屬性,效果會疊加而不是覆蓋)
<p class="stage"> <p class="demo"></p></p>
.stage { width: 200px; height: 200px; border: 1px solid black; margin: 100px auto;}.stage .demo { width: 200px; height: 200px; background-color: orangered; transform: rotateX(45deg);}
在這個例子中,我們把內部元素繞x軸旋轉了45°後
由於他只是在二次元旋轉,所以我們根本看不出來它旋轉
但是我們現在加個景深
.stage { width: 200px; height: 200px; border: 1px solid black; margin: 100px auto; perspective: 500px; /*增*/}.stage .demo { width: 200px; height: 200px; background-color: orangered; transform: rotateX(45deg);}
這就相當於我們在舞台元素的中心位置往裡看,這個子項目距離我們肉眼有500px
由於子項目的順時針旋轉,
元素上半部分離我們遠,所以看起來很小
元素下半部分離我們近,所以看起來稍大
這樣就會產生很強的立體感
剛才我說道我們的肉眼相當於在舞台元素中心的位置
其實這個“眼睛”的位置是可以調整的
這用到了perspective-origin屬性
預設的屬性值就是 50% 50%
也就是舞台元素的中心位置
我們可以嘗試調整視角
.stage { width: 200px; height: 200px; border: 1px solid black; margin: 100px auto; perspective: 500px; perspective-origin: 10px 10px; /*增*/}.stage .demo { width: 200px; height: 200px; background-color: orangered; transform: rotateX(45deg);}
這就相當於在舞台元素的距離原點(左上)10px,10px的位置往裡看
理解這個需要我們一定的空間立體感
注意:景深大小一定要比你的動畫元素大(我們不可能看到眼睛後面的東西)
景深的另一種用法,是應用在動畫元素(不是舞台元素)變形的函數中
和其他變形函數寫在一起
.stage .demo { ...... transform: rotateX(45deg) perspective(100px);}
3D屬性transform-style
這個屬性指定了子項目如何在空間中展示
只有兩個屬性值:flat(預設)和preserve-3d
flat 表示所有子項目在2D平面呈現
preserve-3d 表示所有子項目在3D平面呈現
(prederve是保護、維持的意思,preserve-3d就是保持三維空間的意思)
當然如果我們想要3D的效果,就要使用 transform-style: preserve-3d;
這個屬性只是針對設定屬性元素的子項目如何展示
而對子項目的子項目無效
而且對於設定了overflow: hidden;
的元素,設定3D效果會失效
道理很簡單,跳出了父元素平面的子項目無法顯示了,結果自然還是2D效果
應用於這個屬性的元素我們稱作“容器”
這個屬性我們下面通過一個例子再來體會
背面可見屬性backface-visibility
通過這個元素我們可以指定當元素背對我們時是否可見
只有兩個屬性值visibility(預設)和hidden
如果我們希望元素背對我們不可見
就這樣設定
.demo { ... backface-visibility: hidden;}
下面我通過一個例子來把上面講到的屬性全部實踐一下
樣本:旋轉的三維立方體
<p class="stage"> <!--舞台元素,視角所在--> <ul class="three-d-box"> <!--動畫容器,通過它來控制整個立方體--> <li></li> <!--動畫元素,立方體的六個面--> <li></li> <li></li> <li></li> <li></li> <li></li> </ul></p>
ul { /*調整ul標籤的樣式,取消內邊距、外邊距,和“點”樣式*/ padding: 0; margin: 0; list-style-type: none;}.stage { /*設定舞台元素在螢幕置中,設定合適的景深大小*/ position: relative; width: 800px; height: 800px; margin: 100px auto; perspective: 800px;}@keyframes move { /*設定動畫主要畫面格*/ 0% { transform: rotateX(0deg); } 25% { transform: rotateX(180deg); } 50% { transform: rotateX(360deg) rotateY(0deg); } 75% { transform: rotateX(360deg) rotateY(180deg); } 100% { transform: rotateX(360deg) rotateY(360deg); }}.stage .three-d-box { /*動畫容器置中在舞台元素中間*/ width: 200px; height: 200px; position: absolute; left: 50%; top: 50%; margin: -100px 0 0 -100px; transform-style: preserve-3d; /*設定3D屬性讓子項目三維空間呈現*/ animation: move 3s linear infinite; /*設定動畫*/}.stage .three-d-box>li { /*設定動畫子項目公用屬性*/ position: absolute; width: 200px; height: 200px; left: 0; top: 0; font-size: 50px; line-height: 200px; text-align: center; opacity: 0.5;}/*為了保證我們對立方體位置的控制,我們需要讓動畫容器在立方體的中間位置*/.stage .three-d-box>li:nth-child(1) { background-color: red; transform: translateZ(-100px);}.stage .three-d-box>li:nth-child(2) { background-color: greenyellow; transform: translateZ(100px);}.stage .three-d-box>li:nth-child(3) { background-color: cornflowerblue; transform: rotateX(90deg) translateZ(100px);}.stage .three-d-box>li:nth-child(4) { background-color: orangered; transform: rotateX(-90deg) translateZ(100px);}.stage .three-d-box>li:nth-child(5) { background-color: deeppink; transform: rotateY(90deg) translateZ(100px);}.stage .three-d-box>li:nth-child(6) { background-color: lightcoral; transform: rotateY(-90deg) translateZ(100px);}
大功告成
這樣我們就會得到如下酷炫的三維立方體
注意在3D變換transform中,旋轉與位移函數的順序不同,元素展現的位置是不同的
這是因為元素的座標軸是隨著我們變換而變化的
上面的代碼如果有不明白的地方,可以拷貝到瀏覽器進行調試
整體的思路就是
設定舞台元素(perspective:xxxpx)
設定動畫容器(transform-style:preserve-3d)
通過旋轉、位移調整動畫子項目的位置
對動畫容器應用動畫效果
最後我們通過這個正方體來加深三維變換相關屬性的理解
backface-visibility
添加樣式前的正方體
現在我們來添加樣式
.stage .three-d-box>li { ...... backface-visibility: hidden;}
大家來找茬
可以看到背對我們的元素全部看不見了
這就是backface-visibility: hidden;
的作用
還有一些旋轉、縮放、平移的屬性這裡我就不再測試了
大家可以開啟控制台自己體會一下,和2D中的用法是類似的