深入解讀CSS3中transform變換模型的渲染

介紹
transform是通過一系列矩陣變換完成的,scale等transform-function都是對matrix的封裝。
w3里的解釋是,transform基于可視化格式模型(visual formatting model,這樣翻譯對不對?。┎槠淅L制出一個(gè)坐標(biāo)系,而且所有在這個(gè)坐標(biāo)系內(nèi)進(jìn)行的操作,如向右向下,都是在這個(gè)坐標(biāo)系內(nèi)以像素方式表示
元素設(shè)置了transform并不會(huì)改變元素所在的文檔流,其布局仍然受盒模型支配,因此這里的變換的效果是可以與浮動(dòng)、定位并存的。
當(dāng)元素設(shè)置了transform后,會(huì)為該元素定義一個(gè)坐標(biāo)系,并且在該坐標(biāo)系內(nèi)進(jìn)行矩陣變換,將變換結(jié)果映射到用戶坐標(biāo)系(也就是實(shí)際上的上下文)中。
多個(gè)矩陣變換函數(shù)將依次從左到右計(jì)算,如transform:translate(80px, 80px) scale(1.5, 1.5),瀏覽器會(huì)先計(jì)算位移,再縮放1.5倍。以下兩種代碼效果相同:
html
- <div style="transform: translate(80px, 80px)">
- <div style="transform: scale(1.5, 1.5)">
- <div style="transform: rotate(45deg)"></div>
- </div>
- </div>
html
- <div style="transform: translate(80px, 80px) scale(1.5, 1.5) rotate(45deg);">
- </div>
坐標(biāo)原點(diǎn)的位置受屬性 transform-origin的影響。
如果是3D變換,則還會(huì)將其加入一個(gè)3D渲染上下文(3D rendering context)。根據(jù)個(gè)人理解,無論有多少個(gè)轉(zhuǎn)換為3D的元素,其將始終在這個(gè)上下文內(nèi)并可能相互影響,類似一個(gè)文檔中的多個(gè)被絕對定位的元素。
任何非none的transform值都會(huì)導(dǎo)致一個(gè)堆疊上下文(stacking context)和包含塊(containing block)的創(chuàng)建。
變換渲染模型
為transform屬性指定一個(gè)除了none的值便會(huì)在元素上創(chuàng)建一個(gè)新的局部坐標(biāo)系統(tǒng)并且應(yīng)用于這個(gè)元素。通過元素的變換模型,元素可以繪制渲染出自己的坐標(biāo)系統(tǒng)。變換是可以積累的。也就是說,元素可以通過父元素的坐標(biāo)的系統(tǒng)來建立自己的局部坐標(biāo)系統(tǒng)。從用戶的視角看,一個(gè)元素不但可以從它的祖先元素上有效的積累transform屬性,而且也可以給自己增加transform屬性并應(yīng)用與自己。這些變換的積累為元素描繪出了當(dāng)前的變換模型。
帶有兩個(gè)軸的坐標(biāo)空間:X軸水平向右為正,Y軸垂直向下為正。立體的變換函數(shù)增加了坐標(biāo)空間將其延生至了三維空間,增加的Z軸垂直與屏幕,并且面向觀察者的方向?yàn)檎?也就是電腦屏幕前的我們)。如圖。
變換模型通過如下的transform和transform-origin屬性進(jìn)行計(jì)算
從具體的模型開始
通過transfrom-origin的X,Y,Z計(jì)算值進(jìn)行移動(dòng)
從左到右復(fù)合應(yīng)用在transform屬性中的transform functions
使之前設(shè)置的transform-origin的值無效并進(jìn)行移動(dòng)
EXAMPLE1
- div {
- transform: translate(100px,100px);
- }
EXAMPLE2
- div {
- height: 100px;
- width: 100px;
- transform-origin: 50px 50px;
- transform:rotate(45deg)
- }
transform-origin通過在X,Y軸方向上各移動(dòng)50px來移動(dòng)原點(diǎn)。元素沿著原點(diǎn)順時(shí)針旋轉(zhuǎn)了45°。當(dāng)所有的transform functions都應(yīng)用后,平移后的原點(diǎn)在X,Y軸上又各移動(dòng)了-50px,回到了原來的位置。如圖
理解
上面的話的意思就是,transform-origin的起始點(diǎn)是在原點(diǎn)的位置,旋轉(zhuǎn)圍繞著transform-origin在轉(zhuǎn),移動(dòng)transform-origin是從原點(diǎn)開始的,而不是transform-origin的默認(rèn)位置開始移動(dòng)的(默認(rèn)為元素中心,上例恰好也剛剛好移動(dòng)到元素的中心位置),transform-origin移動(dòng)完后,并在元素上已經(jīng)將transform functions應(yīng)用完后,平移后的原點(diǎn)便會(huì)回到原來的位置,也就是說,下次改變transform-origin的位置仍然是從起始點(diǎn)算起(也就是之前的原點(diǎn))。
EXAMPLE3
以下所涉圖片深綠色部分均是沒有使用變換屬性時(shí)元素的本來樣子。
- div {
- height: 100px;
- width: 100px;
- transform: translate(80px,80px) scale(1.5,1.5) rotate(45deg);
- }
首先在X,Y軸上各移動(dòng)80px,然后將元素放大150%,接著沿著Z軸方向順時(shí)針旋轉(zhuǎn)45°。
注意:縮放和旋轉(zhuǎn),都是通過元素的中心進(jìn)行運(yùn)轉(zhuǎn)的,因?yàn)樵氐哪J(rèn)transfrom-origin值為50% 50%。
通過嵌套元素可以實(shí)現(xiàn)與上面相同的效果
- <div style="transform: translate(80px, 80px)">
- <div style="transform: scale(1.5, 1.5)">
- <div style="transform: rotate(45deg)"></div>
- </div>
- </div>
3D變換渲染
通常,元素都是依照平面進(jìn)行渲染,并且被渲染的元素與它們的包含塊的平面一致。平面的transform functions可以改變元素的表現(xiàn),但是它仍然在與它的包含塊相同的平面里進(jìn)行渲染。
三維的變換會(huì)導(dǎo)致變換模型有著一個(gè)非0的Z組件(Z軸投射在屏幕的外面)。這樣可以造成元素可以在不同的平面進(jìn)行渲染,而不是在它的包含塊的平面內(nèi)進(jìn)行渲染。這也可能會(huì)影響一個(gè)元素和與之有聯(lián)系的另一個(gè)元素從前到后的渲染順序,同時(shí)和導(dǎo)致與其他元素發(fā)生交叉。這樣的表現(xiàn)依賴于這個(gè)元素是否為3D rendering context中的一員,正如下所說
上面的描述并不會(huì)完全準(zhǔn)確的在WebKit中是實(shí)現(xiàn)。也許它會(huì)被改變來適應(yīng)現(xiàn)在的是實(shí)現(xiàn)?See,Bug 19637
EXAMPLE4
- div {
- height: 150px;
- width: 150px;
- }
- .container {
- border: 1px solid black;
- background-color: #ccc;
- }
- .transformed {
- transform: rotateY(50deg);
- background-color: blue;
- }
- <div class="container">
- <div class="transformed"></div>
- </div>
這次變換是一個(gè)圍繞著垂直的Y軸進(jìn)行的50度旋轉(zhuǎn)。但是為什么這次變換為什么使的盒子便窄了呢?而不是變得立體呢?
perspective和perspective-origin屬性可以通過使元素在Z軸變得更高而使元素顯得更大,以此來增加觀者在空間深度上的感知,同時(shí)也可以通過同樣的方法使之顯得越小??s放比例的比例項(xiàng)公式是d/(d-Z),perspective的值就是從繪制平面到假設(shè)的觀者眼睛的位置。
上圖用圖形解釋了縮放比例是如何依賴于perspective屬性和Z的值。在上面的那張圖,Z值是d的一半。原始的圓圈(實(shí)線圓圈)出現(xiàn)在Z上(虛線圈),為了是它呈現(xiàn)在畫面中,圓圈通過以上兩個(gè)要素按比例放大,最后在畫面中呈現(xiàn)出來了放大的淺藍(lán)色圓圈。下面的圖形,圓圈通過比例進(jìn)行縮小出現(xiàn)在原始位置后面的1/3圓圈,最后在畫面中呈現(xiàn)出了縮小的淺藍(lán)色圓圈。
通常假設(shè)觀察者眼睛的位置在畫面的中央。但是,如果想的話,這個(gè)位置也是可以移動(dòng)的-例如,如果一個(gè)網(wǎng)頁包含了很多圖畫那么大家通過設(shè)置perspective-origin的值來分享相同的視角。
圖形表現(xiàn)了向上移動(dòng)perspective origin對表現(xiàn)效果的影響
透視模型按如下進(jìn)行計(jì)算:
1.從具體的模型開始
2.通過 設(shè)置的perspective-origin的X,Y的計(jì)算值進(jìn)行移動(dòng)
3.通過獲得perspective屬性的值應(yīng)用在模型上
4.使之前設(shè)置的perspective- origin的值無效并進(jìn)行移動(dòng)
EXAMPLE5
這個(gè)例子表現(xiàn)了透視可以被用來表達(dá)立體的變換從而顯現(xiàn)出更多真實(shí)的細(xì)節(jié)
- div {
- height: 150px;
- width: 150px;
- }
- .container {
- perspective: 500px;
- border: 1px solid black;
- background-color: #ccc;
- }
- .transformed {
- transform: rotateY(50deg);
- background-color: blue;
- }
- <div class="container">
- <div class="transformed"></div>
- </div>
里面的元素和在前面的例子中有著相同的變換,但是它的渲染被父元素上的perspective屬性所影響。透視給予了一個(gè)顯現(xiàn)的深度,導(dǎo)致頂點(diǎn)有了Z坐標(biāo)(靠近觀察者)使其在X,Y軸被放大,并且更進(jìn)一步的(在負(fù)的Z軸上)也會(huì)被縮小。
一個(gè)并不包含在3D渲染上下文中的立體變換元素有著合適的transform值進(jìn)行渲染,但是也不會(huì)與其他任何元素發(fā)生相交。在這個(gè)EXAMPLE4中的立體變換可以被考慮為一種繪畫效果,就像平面中的變換。相似的,變換不會(huì)影響渲染命令。舉個(gè)例子,在transform中設(shè)置Z的值使元素進(jìn)行移動(dòng)可能使元素變得更大,但是并不會(huì)導(dǎo)致元素去渲染它前面沒有設(shè)置Z值的元素
一個(gè)包含在3D渲染上下文的立體變換元素在同樣的3D渲染上下文中可以與其他元素相交;參與相同3D渲染上下文的元素,根據(jù)它們的變換結(jié)果,可能會(huì)互相隱藏或者相交。在同樣的3D坐標(biāo)空間擺放,使它們好像全部都是兄弟姐妹。一個(gè)元素在立體空間中擺放的位置決定于從建立3D渲染上下文的包含塊中積累的變換模型所決定。
EXAMPLE6
- div {
- height: 150px;
- width: 150px;
- }
- .container {
- perspective: 500px;
- border: 1px solid black;
- background: #ccc;
- }
- .transformed {
- transform: rotateY(50deg);
- background-color: blue;
- }
- .child {
- transform-origin: top left;
- transform: rotateX(40deg);
- background-color: lime;
- }
- <div class="container">
- <div class="transformed">
- <div class="child"></div>
- </div>
- </div>
這個(gè)例子表現(xiàn)了嵌套的3D變換元素在缺少transform-style: preserve-3d時(shí)是如何渲染的。藍(lán)色的div和之前的例子變換結(jié)果是一樣的,都是被父元素的perspective屬性所影響。綠黃色的元素同樣有繞著X軸進(jìn)行旋轉(zhuǎn)的3D變換。然而,綠黃色元素在它的父元素所在平面進(jìn)行渲染因?yàn)樗皇?D渲染上下文中的一員;父元素是二維的。
按照如下規(guī)則,元素可建立并參與在3D渲染上下文中:
3D渲染上下文通過有著transform-style: preserved-3d值的變換元素創(chuàng)建并且它自己并不是3D渲染上下文中的一員。這樣的元素通常都是一個(gè)包含塊。一個(gè)元素建立3D渲染上下文同樣也參與其中。
一個(gè)有著transform-style: preserved-3d值的元素,參與在它自己創(chuàng)建的3D渲染上下文中,擴(kuò)大了3D渲染上下文,而不是建立了一個(gè)新的3D渲染上下文。
一個(gè)元素參與3D渲染上下文,除非它的包含塊建立了3D渲染上下文或者擴(kuò)展了3D渲染上下文
最后的變換結(jié)果通常是在3D渲染上下文中渲染的元素3D變換模型的積累,如下:
從具體的模型開始
對于每一個(gè)在3D變換根元素和元素之間的包含塊,考慮以下幾點(diǎn):
1.在元素的包含塊上積累perspective matrix(如果可以的話)。包含塊并不一定要成為3D渲染上下文中的一員
2.元素的offset-parent是相對于它的包含塊的,元素應(yīng)用計(jì)算后的移動(dòng)值等同于垂直水平移動(dòng)。
3.累加變換效果
EXAMPLE7
- div {
- height: 150px;
- width: 150px;
- }
- .container {
- perspective: 500px;
- border: 1px solid black;
- background: #ccc;
- }
- .transformed {
- transform-style: preserve-3d;
- transform: rotateY(50deg);
- background: blue;
- }
- .child {
- transfom-origin: top left;
- transform: rotateX(40deg);
- background-color: lime;
- }
這個(gè)例子和前面的例子是相同的,除了加了一個(gè)transform-style: preserve-3d值在藍(lán)色的元素上。藍(lán)色的元素建立的3D渲染上下文,綠黃色元素是其中一員。現(xiàn)在藍(lán)色和綠黃色元素都被容器中的perspective所影響,并且同時(shí)分享了一個(gè)相同的立體空間,所以淺綠色的元素在它的父元素上擺動(dòng)。
元素在同樣的3D渲染上下文中可能會(huì)彼此相交。
在3D渲染上下文中不變換的元素在Z=0的平面上也有可能與變換元素相交。
在3D渲染上下文里,在應(yīng)用完積累的變換后,沒有相交的元素的渲染順序基于在Z軸上的位置。元素在Z軸的位置相同則渲染順序由層疊上下文決定。
EXAMPLE8
- div {
- width: 150px;
- }
- .container {
- height: 145px;
- background-color: rgba(0,0,0,0.3);
- border: 1px solid black;
- transform-style: preserve-3d;
- perspective: 500px;
- }
- .container>div {
- position: absolute;
- left: 0;
- }
- .container> :first-child {
- transform: rotateY(45deg);
- background-color: orange;
- top: 10px;
- height: 135px;
- }
- .container> :last-child {
- transform: translateZ(40px);
- background-color: rgba(0,0,255,0.75);
- top: 50px;
- height: 100px;
- }
- <div class="container">
- <div></div>
- <div></div>
- </div>
這個(gè)例子展示了,在3D渲染上下文中元素是可以相交的。容器元素為自己創(chuàng)建了3D渲染上下文并且他有兩個(gè)子元素。子元素互相相交,同時(shí)橘黃色的元素也與容器相交。
使用立體變換,讓一個(gè)元素的背面朝著觀者是完全有可能的。3D變換元素在兩面展示相同的內(nèi)容,所以反面看起來就像鏡子中的正面(就像元素映射在一片鏡子上一樣)。通常,元素的反面朝著觀者都會(huì)隱藏。然而,backface-visiblity:hidden屬性允許作者使其不可見當(dāng)元素的反面朝著觀者時(shí)。如果一個(gè)帶有backface-visiblity:hidden屬性的元素是有效的,那么他的前面和背面便會(huì)交替的隱藏,然后,只有當(dāng)前面朝向觀者時(shí)元素才是可見的。
理解backface-visibility屬性
- .wrap {
- width: 200px;
- height: 200px;
- border: 1px solid black;
- perspective: 200px;
- color: #fff;
- text-align: center;
- font-size: 50px;
- }
- .inner {
- width: 50px;
- height: 50px;
- margin: 20px auto;
- background: orange;
- line-height: 50px;
- transform: rotateY(180deg);//旋轉(zhuǎn)180
- }
- <div class="wrap">
- <div class="inner">2</div>
- </div>
圖左為旋轉(zhuǎn)前,圖右為旋轉(zhuǎn)后。
可以看出圖右就像平時(shí)我們照鏡子在鏡子中的投影一樣。這個(gè)就是元素的背面。
接下來當(dāng)我們在元素inner上加backface-visibility:hidden屬性則元素便會(huì)被隱藏,看起來消失了一樣。如圖
相關(guān)文章
CSS3中設(shè)置3D變形的transform-style屬性詳解
transform-style經(jīng)常被用來做三維空間坐標(biāo)系中的圖形變換,下面我們就來看看CSS3中設(shè)置3D變形的transform-style屬性詳解,需要的朋友可以參考下2016-05-23CSS3的常見transformation圖形變化用法小結(jié)
這篇文章主要介紹了CSS3的常見transformation圖形變化用法小結(jié),共整理了旋轉(zhuǎn)、縮放、平移、傾斜以及矩陣的使用方法,需要的朋友可以參考下2016-05-13CSS3中的transform屬性進(jìn)行2D和3D變換的基本用法
這篇文章主要介紹了使用CSS3中的transform屬性進(jìn)行2D和3D變換的基本用法,文中同時(shí)介紹了使用perspective-origin定義初始位置的方法,需要的朋友可以參考下2016-05-12實(shí)例講解CSS3中Transform的perspective屬性的用法
這篇文章主要介紹了CSS3中Transform的perspective屬性的用法,文中詳細(xì)講解了使用perspective屬性對圖片進(jìn)行3D變換的操作,需要的朋友可以參考下2016-04-22使用CSS3的transform 屬性實(shí)現(xiàn)帶前后按鈕3D立體旋轉(zhuǎn)木馬特效源碼
CSS3的transform屬性實(shí)現(xiàn)帶前后按鈕3D立體旋轉(zhuǎn)木馬特效源碼是一款使用CSS3 3D transforms屬性來渲染一個(gè)3D立體旋轉(zhuǎn)木馬,圖片不重疊,并通過簡單的jQuery代碼來控制旋轉(zhuǎn)木2016-03-03基于css3實(shí)現(xiàn)的transform屬性相冊圖片墻特效源碼
css3 transform屬性相冊圖片墻代碼是一款css3動(dòng)畫縮放的照片墻特效代碼2014-12-17- 這篇文章主要介紹了css3的transform中scale縮放的使用方法,需要的朋友可以參考下2014-12-08
- 這篇文章主要介紹了css3的transform造成z-index無效解決方案,需要的朋友可以參考下2014-12-04
- transform 屬性向元素應(yīng)用 2D 或 3D 轉(zhuǎn)換。該屬性允許我們對元素進(jìn)行旋轉(zhuǎn)、縮放、移動(dòng)或傾斜。2014-09-30
- skew(...)的括號里放的是坐標(biāo)軸旋轉(zhuǎn)的角度,那么就可以知道y軸順時(shí)針轉(zhuǎn)為正,X軸逆時(shí)針轉(zhuǎn)為正,需要的朋友可以參考下2014-07-21