css 3D transform變換

麵包屑的獨白發表於2018-12-05

本文主要是總結了筆者在學習3D transform所收穫的經驗,希望通過筆者認為合理的知識點安排,能夠讓大家少走彎路,本文並不涉及2D transform,想了解相關知識的讀者可以google查閱相關資料。希望看完之後能夠有所收穫,不正確地方,也希望大家不吝指教。

什麼是透視

在剛接觸透視這個詞語的時候,可以說大腦是一片空白。到底透視是個什麼概念?為什麼給元素設定了perspective屬性,元素就能表現出3D空間?這事還得從繪畫說起。

透視現象

有一種現象,由於我們從小就己經習慣了,也就從不覺得奇怪,那就是:同樣規格的電線杆本來是一樣高的,但在路上看起來,卻近高遠低;同樣型號的汽車本應是一樣大小的,但在路上看起來卻近大遠小;所有的茶杯、水桶底本來都是平的,但我們時常看到的卻是不同的弧線;火車的兩條路軌本來都是一樣寬的, 但我們時常看到的卻是兩條路軌向前延伸時,會越來越窄乃至合攏成一點等。這種視覺現象就是透視現象,總結來說就是:

  • 近大遠小
  • 近寬遠窄
  • 近實遠虛
css 3D transform變換

我們都知道現實世界是3D的,通過光線的直線傳播最後在視網膜呈現的是平面影象,但是這種影象卻富有立體空間感,以至於不讓我們撞到牆,掉到河裡去。可以說人眼看到的畫面都是透檢視。而我們如果想要在平面的紙上,表現出這種變化,表現出如我們視覺所反映出的、富有立體空間感的景物,簡單的辦法就是:固定你的眼睛位置,隔著透明玻璃窗將你所見的景物的形狀依樣描在玻璃上,這描下來的圖形就會較準確地反映這種現象,就存在著客觀的透視規律。因此,“透視”的含義就是:透過(假設的)透明平面去觀察景物,研究物體在立體空間中的形態變化,即“透而視之”,用這種觀察方法,可以在只有兩度空間的透明平面上錄畫出具有三度空間特徵的景物圖形。這個圖形叫透檢視,最早研究透視的畫家,就是採用這種辦法來做的,透過總結透檢視中的規律得出繪畫透檢視科學的方法,我們稱之為透視學。所以說只要你在二維平面採用透視學中的方法,畫出滿足透視學的圖畫。就能欺騙人的眼睛,讓圖畫富有立體空間感。如下圖所示

css 3D transform變換

透視相關術語

在透檢視中有很多專業的術語,瞭解他們可以讓我們更加容易理解css 3D transform。

css 3D transform變換

視點:就是畫者眼睛的位置。

中視線:由視點作出的射向景物的任何一條直線均為視線,其中引向正前方的視線為中視線,中視線始終垂直於畫面。我們可以把畫面當成是螢幕,perspective屬性值就是中視線的長度。

主點:中視線與視平線的交點(也叫心點).

滅點(消失點 Vanish Point):透檢視中,滅點是一個很重要的概念。在透檢視中相互平行的直線延長會相交於一點,這點就是滅點,也叫消失點(Vanish Point)。根絕透檢視滅點的數量可以分為一點透視,兩點透視,三點透視。perspective-origin就是定義滅點位置。

更多關於透視的基礎概念,希望大家自行google畢竟我們的重點還是專注於前端。

螢幕座標軸

在瞭解透視之前,首先要先了解座標軸。3D變形與2D變形最大的不同就在於其參考的座標軸不同。2D變形的座標軸是平面的,只存在x軸和y軸,而3D變形的座標軸則是x、y、z三條軸組成的立體空間,x軸正向、y軸正向、z軸正向分別朝向右、下和螢幕外。

css 3D transform變換

面向使用者的是z軸,垂直方向是Y軸,水平是X軸。rotateX, rotateY, rotateZ三個方法就是將元素沿著相應的軸進行旋轉。

3D transform屬性各個擊破

在瞭解了一些基本的概念之後我們開始真正進入3D transform的世界。3D變形涉及的屬性主要是transform-origin、transform、transform-style、perspective、perspective-origin、backface-visibility。

perspective屬性

Value:	none | <number>
Initial:	none
Inherited:	no
複製程式碼

我並不想直接引用規範裡的介紹來說明perspective屬性。簡單來說就是設定了perspective屬性的元素,該元素就具有立體空間的表現能力。不過僅對該元素的子元素有效,元素本身並不具有立體空間表現能力.perspective值定義了中視線的長度,直觀說法就是使用者眼睛到螢幕的距離,官方說法就是z=0的平面和使用者之間的距離,每一個3d元素z>0則越大,z<0則越小,3d效果的強烈程度隨著perspective值得增大而減小,當perspective值為none,小於或等於0不存在 3d變形。

See the Pen no-perspective by joker (@sponia-joker) on CodePen.

建議在進行3d transform時候,採用上面的html結構。舞臺元素,容器元素,變形元素這樣可以讓模型保持簡單而且容易理解。在上面demo中,我們將子元素沿Y軸旋轉了45deg,但是頁面並沒有表現出我們期待的效果,實際效果是變形元素的寬度縮小。這是因為我們並沒有給父元素設定perspective屬性,元素不具備立體空間的表現能力,最終表現的是元素沿Y軸旋轉之後再螢幕上的投影,所以寬度會縮小。但我們開啟註釋後,就會是我們期待的效果。大家可以在codepen上手動實踐下。

perspective屬性有兩種書寫形式,一種用在舞臺元素上(動畫元素們的共同父輩元素);第二種就是用在當前變形元素上,與transform的其他屬性寫在一起。如下所示

See the Pen perspective-function by joker (@sponia-joker) on CodePen.

最後的效果和在父元素上設定perspective屬性是一模一樣。但兩個屬性還是有很大區別,之所以上面效果是一樣,是因為舞臺上只有一個元素,如果有多個元素就會表現出差異。

See the Pen perspective-vs-perspective-function by joker (@sponia-joker) on CodePen.

顯然當具有多個元素時候,perspective和perspective()函式具有不同表現效果。主要是因為在父元素上設定perspective屬性,所有子元素具有相同的視點,而配合transform使用的perspective函式每個元素都擁有各自不同的視點。可以理解成1個人看 vs 5個人看。更加不可思議的是但設定perspective為100px時,給父元素設定perspective屬性的demo中,倒數第二個元素會消失,這裡讀者可以仔細思考下,如果想不明白可以評論留言。

總結來說就是perspective賦予了元素3d空間展示的能力,可以說:無透視,不成3D。更多關於perspective屬性的說明,強烈建議讀者去規範MDN瞭解。

transform-style屬性

value:flat | preserve-3d
Initial:flat
Inherited:no
複製程式碼

Transform-style屬性定義了巢狀元素如何在3D空間進行渲染,當設定為flat時,元素所有子元素都被渲染在元素所在的2D平面,因此,圍繞X軸或Y軸旋轉元素,將導致位於正或負Z位置的子元素出現在元素的平面上,而不是在元素的前面或後面。如果transform-style值為preserve-3d,那麼這種扁平化不會被執行,子元素會在3D空間中保持自己的位置。 元素預設會保持扁平化,又因為該屬性無法繼承,因此為了在3D空間中儲存元素的層次結構需要在層次結構中的每個祖先元素都設定transform-style值為preserve-3d.由於transform-style只會影響元素的子元素,所以層次結構中的葉子節點不需要設定。 一般我們都是設定transform-style屬性值為preserve-3d,為了演示兩者的不同,可以通過點選codepen中的按鈕交替顯示

See the Pen transform-style by joker (@sponia-joker) on CodePen.

perspective-origin屬性

value:x-axis y-axis
Initial:50% 50%
Inherited:no
複製程式碼

perspective-origin屬性比較簡單,他設定視點x,y軸座標。簡單來說就是決定了我們看實物的角度。更詳細說明可以參考

css-tricks有關該屬性的介紹。

backface-visibility屬性

value:visible | hidden
Initial:visible
Inherited:no
複製程式碼

“backface-visibility”屬性決定轉換後的元素的“背面”是否對使用者可見。就好比一枚硬幣,當我們沿Y軸旋轉180deg時候,此時是背面朝向我們,backface-visibility就是用來設定背面是否可見。backface-visibility經常用來實現一些翻轉效果

See the Pen perspect-visibility by joker (@sponia-joker) on CodePen.

參考資料

  1. www.w3.org/TR/2009/WD-…
  2. 3dtransforms.desandro.com/perspective
  3. www.w3cplus.com/css3/transf…
  4. www.cnblogs.com/xiaohuochai…
  5. www.zhangxinxu.com/wordpress/2…
  6. css-tricks.com/almanac/pro…
  7. css-tricks.com/almanac/pro…
  8. blog.sina.com.cn/s/blog_5cd8…

相關文章