摘要:控制攝像機畫面網頁里的攝像機一般是這樣用的在網頁里,無論你搭建了怎樣的三維場景,只要你希望它顯示出來,就應該像這樣把構成場景的三維物體都放在一個容器元素里,然后為容器元素添加攝像機屬性和。
css里的3d理念
使用css3的3d transform,就可以在平面的網頁里添加炫酷的三維視覺效果,這很令人愉悅。
需要注意的是,3d transform只是css的一部分,它并不是一個三維引擎(3d engine)。三維引擎一般是這樣的(游戲引擎Unity3D):
包括JavaScript 3D庫three.js在內,簡單來說,它們這些可以稱為三維引擎的,都會包括:
獨立的三維坐標系統。
幾何圖形和材質貼圖。
光照和攝像機。
3d transform和它們相比起來,是缺少這些內容的。畢竟,css的關注點是網頁樣式,而不是創建虛擬空間。
盡管3d transform的三維空間能力有所不足,但它仍然可以創建出很棒的三維效果。這就需要我們開發者來用心了。
在下面的內容開始之前,如果你還對perspective等3d transform相關的css屬性完全不了解,可以閱讀我以前寫的css三維變換的文章。
3d transform的坐標系統我們很熟悉的網頁是平面的,一個DOM元素,比如一個 每一個DOM元素都有一個這樣的初始坐標系。其中,原點位于元素的左上角,z軸指向觀察者(也就是屏幕外的我們)。初始坐標系的z軸并不算是三維空間,而是像z-index那樣作為參照,決定網頁元素的繪制順序,繪制順序靠后的元素將覆蓋繪制順序靠前的。 在使用transform的時候,情況則有所不同。transform所參照的并不是初始坐標系,而是一個新的坐標系: transform所用的這個坐標系,相比初始坐標系,x、y、z軸的指向都不變,只是原點位置移動到了元素的正中心。如果想要改變這個坐標系的原點位置,使用transform-origin。transform-origin的默認值是50% 50%,因此,默認情況下,transform坐標系的原點位于元素中心。 我們都可能像transform: rotateY(45deg) translateX(100px);這樣使用多個變換函數。這種時候,需要意識到變換函數的順序。這是因為,每一個變換函數不僅改變了元素,同時也會改變和元素關聯的transform坐標系,當變換函數依次執行時,后一個變換函數總是基于前一個變換后的新transform坐標系。 例如,下面一個包含兩個變換函數的transform的效果(gif): 如果交換這兩個變換函數的順序,是這樣的效果: 可以看到,由于坐標系會隨著每一次變換發生改變,因此不同順序的情況下,元素最終的位置也不同。 對此還有一種解釋,即變換函數是通過數學上的矩陣乘法運算完成的,而矩陣的乘法是不滿足交換律的。任意坐標空間內的變換函數或者變換函數的組合,都可以轉換為一個矩陣(還有一個矩陣小工具可以幫你做這個轉換)。 前面已經提到,3d transform并沒有像三維引擎那樣為你創建三維場景提供全面的資源。因此,就以創建一個三維物體來說,我們只能利用網頁目前已有的內容,自己想辦法。 在網頁里,你并不能直接定義一系列坐標為(x, y, z)的空間中的點,然后基于這些點來生成三維圖形。網頁里有的,是平面圖形。不管是 事實上,在三維引擎里,三維物體也不是實體,它們都是由一系列平面(多邊形)所圍成的(并可以在平面上添加紋理和貼圖)。 現在來做一個正方體,現在先不用考慮perspective。正方體有六個面,然后需要用一個元素來裝這六個面,所以html是: 對應的css是(邊長120px,省略瀏覽器私有前綴,后文同): 其中,transform-style: preserve-3d;保證所有子元素都處于同一個三維空間(這里是三維渲染上下文3D rendering context)內,也就是告訴瀏覽器你是想用這些元素做一個三維場景,而不僅僅只是要單個元素的簡單三維效果。 position: absolute;是一個習慣做法,因為三維物體并不符合一般平面網頁內容的排版,所以我們會比較多地希望它不要占據布局空間。 6個面位置都不一樣,但卻都有translateZ(60px);,你已經知道這是因為巧妙搭配了在它之前的變換函數。 一旦構成正方體的6個div.surface的位置確定后,就可以操作它們的父元素div.cube來整體移動、旋轉這個正方體。 只是有了這樣的一個三維物體,我們就可以說有了一個三維場景了。但是,三維場景和平面圖不同,比如這個正方體,我從不同的位置,不同的角度去觀察它,我眼里看到的都是不一樣的: 那么,這樣的三維場景要如何呈現在平面的網頁里呢? 這就是三維引擎里的攝像機的概念來源了。就像電影里表現同一個場景會用不同的鏡頭那樣,我們需要定義場景里的攝像機來生成最終呈現在屏幕里的二維畫面。比如three.js里的攝像機是這樣的感覺: 這個圖里標明的是攝像機定義時使用的參數,其中包括視野范圍,圖像寬高比等??梢愿惺艿竭€是有很多內容的。 相比之下,網頁里的三維場景攝像機就弱多了,你需要用的是perspective和perspective-origin。 perspective定義攝像機(也就是作為觀眾的我們)到屏幕的距離,perspective-origin定義攝像機觀察到的畫面中的滅點(vanishing point)的位置。雖然它們并不能方便地讓你直接定義攝像機的位置和觀察角度等,但只要適當地應用它們,是可以一定程度上控制攝像機的畫面效果的。 網頁里的攝像機一般是這樣用的: 在網頁里,無論你搭建了怎樣的三維場景,只要你希望它顯示出來,就應該像這樣把構成場景的三維物體都放在一個容器元素里,然后為容器元素添加攝像機屬性(perspective和perspective-origin)。 此外,還需要注意添加transform-style: preserve-3d;以保證多個三維物體都位于同一空間(這樣才有三維引擎的味道,對吧?)。 下面這個場景里有三個正方體,然后攝影師正在做彈跳練習(限支持3d transform的瀏覽器): http://runjs.cn/detail/daqoq5tf 這段動作的動畫代碼是這樣: 可以看出,perspective-origin雖然是指三維透視的滅點的位置,但它的確和我們理解的攝像機的位置是緊密關聯的。如果攝像機在空間里的位置是(x, y, z)的話,perspective-origin的兩個值有一點像指定x和y的感覺。這里只說“有一點像”,是因為滅點位置和攝像機的位置畢竟是不同的概念,這可能還需要多看一些三維空間來體會。 那么,在上面的例子中,攝影師不只是這樣跳起來,而是想要向更深處前進,應該怎么做呢? 答案是,在網頁里,你不能這樣移動攝像機,你需要換一個思路,參照相對運動的關系,改為讓整個三維場景向你移動。不過,說到這里,前面提到的攝像機的另一個屬性,perspective,為什么它不行呢? perspective代表攝像機距離屏幕的距離,看上去和z軸深度非常近似。但是,它并不等同于攝像機的z坐標位置(perspective還只能取正值),而是會影響攝像機本身的其他屬性。下面用這個圖說明perspective的值變化的效果(修改自w3c的配圖): 圖中d1和d2分別表示兩個不同的perspective的值,其中d2小于d1。然后,你會驚奇地發現,一個原本位于屏幕之后(z坐標為負值)的物體,竟然是隨著“走近”而變得更小了!顯然,這不符合我們在三維空間里運動的基本感受。其原因是,網頁的三維投影平面是固定的,perspective在改變攝像機的位置的同時,也同時改變了攝像機本身的其他屬性(類似前面的three.js的攝像機那張圖里的各種參數)。 所以,一般來說,perspective應維持一個固定的值。想要用3d transform做出在三維空間里自由移動的效果(就像各種3d游戲),應該通過相對運動的方法實現。 transform影響的是視覺渲染,而不是布局。因此,除以下情況外,transform不會影響到布局: 這個因為overflow生成滾動條從而影響布局的反例,也發生于position: relative;再進行偏移的情況。 相對于transform的translate3d()這類改變空間位置的變換函數,原來css里就有的定位屬性left、top似乎會讓情況變得很復雜。 對此,有一個比較推薦的分析方式:就三維空間的位置而言,常規屬性left、top,甚至margin-left等,是先生效的,它們的效果其實只有一個,就是改變元素的初始位置,從而改變元素的transform-origin的那個原點位置,然后三維空間的transform是后生效的,它會再基于前面的transform-origin繼續改變位置。 現在你已經了解到,perspective-origin是一個攝像機的屬性,定義的是透視畫面的滅點,而transform-origin是任意元素都有的,定義的是的元素的transform坐標系的原點。 本文是我對目前網頁里用3d transform創建三維空間的總結,其中混入了一些三維引擎的知識,并對比著來一一說明。感覺3d transform還是有自己比較明確的定位的,雖然和三維引擎相比很簡陋,但它已經足夠用來為網頁添加吸引人的三維效果。 如果你也想過用3d transform做稍復雜的三維空間,希望本文能有所幫助。 (重新編輯自我的博客,原文地址:http://acgtofe.com/posts/2015/12/xyz-3d-in-css) 文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。 轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/111247.html 摘要:如題,祖先元素非時,記錄一下中引起后代元素參考視圖怪異表現和解決方案。不為元素預留空間,而是通過指定元素相對于屏幕視口的位置來指定元素位置。打印時,元素會出現在的每頁的固定位置。
如題,祖先元素transform非none時,記錄一下Iphone6中引起后代元素fixed參考視圖怪異表現和解決方案。
層疊關系及參考視圖
層疊上下文是HTML元素的三維概念,這些HTML元素在一條假想的相... 摘要:如題,祖先元素非時,記錄一下中引起后代元素參考視圖怪異表現和解決方案。不為元素預留空間,而是通過指定元素相對于屏幕視口的位置來指定元素位置。打印時,元素會出現在的每頁的固定位置。
如題,祖先元素transform非none時,記錄一下Iphone6中引起后代元素fixed參考視圖怪異表現和解決方案。
層疊關系及參考視圖
層疊上下文是HTML元素的三維概念,這些HTML元素在一條假想的相... 摘要:實現方法可參考這篇文章純打造的模型渲染器實現全景。天空盒子相信很多打造過或有了解過全景的同行們都知道這個概念。首先將創建好的六個面切割出來,以命名標記位置。柱形柱形全景也不算復雜。
前言
對的,本文就是著重介紹如何使用CSS3中的3D變換打造出H5中的3D效果。靈感來源于造物節團隊的3d引擎,因為使用方法比較復雜,也沒有開源的API文檔,于是想自己另外造個輪子,便開始了相關內容的學習和... 摘要:一過渡一的作用二的屬性二和動畫一動畫序列書寫簡例二書寫簡例常用屬性簡寫屬性三完整動畫簡例代碼三轉換一轉換縮放移動旋轉設置元素轉換的中心點綜合性寫法二轉換三維坐標系透視呈現位移旋轉一過渡一的作用如果你有一個盒子,他的體內也有個小盒子。 ....cube{
position: absolute;
transform-style: preserve-3d;
}
.cube .surface{
position: absolute;
width: 120px;
height: 120px;
border: 1px solid #ccc;
background: rgba(255,255,255,0.8);
box-shadow: inset 0 0 20px rgba(0,0,0,0.2);
line-height: 120px;
text-align: center;
color: #333;
font-size: 100px;
}
.cube .surface-1 {
transform: translateZ(60px);
}
.cube .surface-2 {
transform: rotateY(90deg) translateZ(60px);
}
.cube .surface-3 {
transform: rotateX(90deg) translateZ(60px);
}
.cube .surface-4 {
transform: rotateY(180deg) translateZ(60px);
}
.cube .surface-5 {
transform: rotateY(-90deg) translateZ(60px);
}
.cube .surface-6 {
transform: rotateX(-90deg) translateZ(60px);
}
.camera{
position: relative;
perspective: 1200px;
perspective-origin: 50% 50%;
transform-style: preserve-3d;
}
.camera{
animation: cameraMove 2s ease-out infinite alternate both;
}
@keyframes cameraMove{
0%{
perspective-origin: 50% 180px;
}
100%{
perspective-origin: 50% -200px;
}
}
相關文章
祖先元素transform非none時在Iphone6上引起后代fixed/absolute元素的怪
祖先元素transform非none時在Iphone6上引起后代fixed/absolute元素的怪
H5打造3d場景不完全攻略(二): Amazing CSS3D
不會做動畫的程序猿不是好的動畫師(如何用css3動畫做動畫)
發表評論
0條評論
閱讀 2600·2021-11-15 11:38
閱讀 2618·2021-11-04 16:13
閱讀 17981·2021-09-22 15:07
閱讀 1014·2019-08-30 15:55
閱讀 3261·2019-08-30 14:15
閱讀 1663·2019-08-29 13:59
閱讀 3207·2019-08-28 18:28
閱讀 1575·2019-08-23 18:29