欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

segmentfault   發(fā)布時(shí)間:2016-05-27 13:07:22   作者:Murphywuwu   我要評論
transform通過一組函數(shù)實(shí)現(xiàn)了對盒子大小、位置、角度的2D或者3D變換,這里我們主要來深入解讀CSS3中transform變換模型的渲染,尤其是關(guān)注web端3D渲染動(dòng)畫的朋友千萬不要錯(cuò)過

介紹

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

CSS Code復(fù)制內(nèi)容到剪貼板
  1. <div style="transform: translate(80px, 80px)">   
  2.   <div style="transform: scale(1.5, 1.5)">   
  3.        <div style="transform: rotate(45deg)"></div>   
  4.   </div>   
  5. </div>  

html

CSS Code復(fù)制內(nèi)容到剪貼板
  1. <div style="transform: translate(80px, 80px) scale(1.5, 1.5) rotate(45deg);">   
  2.  </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)檎?也就是電腦屏幕前的我們)。如圖。
2016527121429287.png (300×244)

變換模型通過如下的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

CSS Code復(fù)制內(nèi)容到剪貼板
  1. div {   
  2.   transform: translate(100px,100px);   
  3. }  

2016527121453089.png (800×394)

EXAMPLE2

CSS Code復(fù)制內(nèi)容到剪貼板
  1. div {   
  2.   height100px;   
  3.   width100px;   
  4.   transform-origin: 50px 50px;   
  5.   transform:rotate(45deg)   
  6. }  

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,回到了原來的位置。如圖
2016527121511177.png (800×308)

理解
上面的話的意思就是,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í)元素的本來樣子。

CSS Code復(fù)制內(nèi)容到剪貼板
  1. div {   
  2.   height100px;   
  3.   width100px;   
  4.   transform: translate(80px,80px) scale(1.5,1.5) rotate(45deg);   
  5. }   

首先在X,Y軸上各移動(dòng)80px,然后將元素放大150%,接著沿著Z軸方向順時(shí)針旋轉(zhuǎn)45°。
2016527121529967.png (300×300)

注意:縮放和旋轉(zhuǎn),都是通過元素的中心進(jìn)行運(yùn)轉(zhuǎn)的,因?yàn)樵氐哪J(rèn)transfrom-origin值為50% 50%。

通過嵌套元素可以實(shí)現(xiàn)與上面相同的效果

XML/HTML Code復(fù)制內(nèi)容到剪貼板
  1. <div style="transform: translate(80px, 80px)">  
  2.   <div style="transform: scale(1.5, 1.5)">  
  3.       <div style="transform: rotate(45deg)"></div>  
  4.   </div>  
  5. </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

CSS Code復(fù)制內(nèi)容到剪貼板
  1. div {   
  2.   height150px;   
  3.   width150px;   
  4. }   
  5. .container {   
  6.   border1px solid black;   
  7.   background-color#ccc;   
  8. }   
  9. .transformed {   
  10.   transform: rotateY(50deg);   
  11.   background-colorblue;   
  12. }  
XML/HTML Code復(fù)制內(nèi)容到剪貼板
  1. <div class="container">  
  2.   <div class="transformed"></div>  
  3. </div>  

2016527121546448.png (335×333)

這次變換是一個(gè)圍繞著垂直的Y軸進(jìn)行的50度旋轉(zhuǎn)。但是為什么這次變換為什么使的盒子便窄了呢?而不是變得立體呢?

perspective和perspective-origin屬性可以通過使元素在Z軸變得更高而使元素顯得更大,以此來增加觀者在空間深度上的感知,同時(shí)也可以通過同樣的方法使之顯得越小??s放比例的比例項(xiàng)公式是d/(d-Z),perspective的值就是從繪制平面到假設(shè)的觀者眼睛的位置。
2016527121622765.png (800×696)

上圖用圖形解釋了縮放比例是如何依賴于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的值來分享相同的視角。
2016527121645443.png (800×411)

圖形表現(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é)

CSS Code復(fù)制內(nèi)容到剪貼板
  1. div {   
  2.   height150px;   
  3.   width150px;   
  4. }   
  5. .container {   
  6.   perspective: 500px;   
  7.   border1px solid black;   
  8.   background-color#ccc;   
  9. }   
  10. .transformed {   
  11.   transform: rotateY(50deg);   
  12.   background-colorblue;   
  13. }   
XML/HTML Code復(fù)制內(nèi)容到剪貼板
  1. <div class="container">  
  2.   <div class="transformed"></div>  
  3. </div>  

2016527121702837.png (300×262)

里面的元素和在前面的例子中有著相同的變換,但是它的渲染被父元素上的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

CSS Code復(fù)制內(nèi)容到剪貼板
  1. div {   
  2.   height150px;   
  3.   width150px;   
  4. }   
  5. .container {   
  6.   perspective: 500px;   
  7.   border1px solid black;   
  8.   background#ccc;   
  9. }   
  10. .transformed {   
  11.   transform: rotateY(50deg);   
  12.   background-colorblue;   
  13. }   
  14. .child {   
  15.   transform-origin: top left;   
  16.   transform: rotateX(40deg);   
  17.   background-colorlime;   
  18. }  
JavaScript Code復(fù)制內(nèi)容到剪貼板
  1. <div class="container">   
  2.   <div class="transformed">   
  3.     <div class="child"></div>   
  4.   </div>   
  5. </div>  

2016527121720789.png (300×250)

這個(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

CSS Code復(fù)制內(nèi)容到剪貼板
  1. div {   
  2.   height150px;   
  3.   width150px;   
  4. }   
  5. .container {   
  6.   perspective: 500px;   
  7.   border1px solid black;   
  8.   background#ccc;   
  9. }   
  10. .transformed {   
  11.   transform-style: preserve-3d;   
  12.   transform: rotateY(50deg);   
  13.   backgroundblue;   
  14. }   
  15. .child {   
  16.   transfom-origin: top left;   
  17.   transform: rotateX(40deg);   
  18.   background-colorlime;   
  19. }  

這個(gè)例子和前面的例子是相同的,除了加了一個(gè)transform-style: preserve-3d值在藍(lán)色的元素上。藍(lán)色的元素建立的3D渲染上下文,綠黃色元素是其中一員。現(xiàn)在藍(lán)色和綠黃色元素都被容器中的perspective所影響,并且同時(shí)分享了一個(gè)相同的立體空間,所以淺綠色的元素在它的父元素上擺動(dòng)。
2016527121737568.png (300×245)

元素在同樣的3D渲染上下文中可能會(huì)彼此相交。

在3D渲染上下文中不變換的元素在Z=0的平面上也有可能與變換元素相交。

在3D渲染上下文里,在應(yīng)用完積累的變換后,沒有相交的元素的渲染順序基于在Z軸上的位置。元素在Z軸的位置相同則渲染順序由層疊上下文決定。
EXAMPLE8

CSS Code復(fù)制內(nèi)容到剪貼板
  1. div {   
  2.  width150px;   
  3. }   
  4. .container {   
  5.  height145px;   
  6.  background-color: rgba(0,0,0,0.3);   
  7.  border1px solid black;   
  8.  transform-style: preserve-3d;   
  9.  perspective: 500px;   
  10. }   
  11. .container>div {   
  12.  positionabsolute;   
  13.  left: 0;   
  14. }   
  15. .container> :first-child {   
  16.  transform: rotateY(45deg);   
  17.  background-color: orange;   
  18.  top10px;   
  19.  height135px;   
  20. }   
  21. .container> :last-child {   
  22.  transform: translateZ(40px);   
  23.  background-color: rgba(0,0,255,0.75);   
  24.  top50px;   
  25.  height100px;   
  26. }  
XML/HTML Code復(fù)制內(nèi)容到剪貼板
  1. <div class="container">  
  2.   <div></div>  
  3.   <div></div>  
  4. </div>  

這個(gè)例子展示了,在3D渲染上下文中元素是可以相交的。容器元素為自己創(chuàng)建了3D渲染上下文并且他有兩個(gè)子元素。子元素互相相交,同時(shí)橘黃色的元素也與容器相交。
2016527121757800.png (300×289)

使用立體變換,讓一個(gè)元素的背面朝著觀者是完全有可能的。3D變換元素在兩面展示相同的內(nèi)容,所以反面看起來就像鏡子中的正面(就像元素映射在一片鏡子上一樣)。通常,元素的反面朝著觀者都會(huì)隱藏。然而,backface-visiblity:hidden屬性允許作者使其不可見當(dāng)元素的反面朝著觀者時(shí)。如果一個(gè)帶有backface-visiblity:hidden屬性的元素是有效的,那么他的前面和背面便會(huì)交替的隱藏,然后,只有當(dāng)前面朝向觀者時(shí)元素才是可見的。

理解backface-visibility屬性

CSS Code復(fù)制內(nèi)容到剪貼板
  1. .wrap {   
  2.   width200px;   
  3.   height200px;   
  4.   border1px solid black;   
  5.   perspective: 200px;   
  6.   color#fff;   
  7.   text-aligncenter;   
  8.   font-size50px;   
  9. }   
  10. .inner {   
  11.   width50px;   
  12.   height50px;   
  13.   margin20px auto;   
  14.   background: orange;   
  15.   line-height50px;   
  16.   transform: rotateY(180deg);//旋轉(zhuǎn)180   
  17. }  
XML/HTML Code復(fù)制內(nèi)容到剪貼板
  1. <div class="wrap">  
  2.   <div class="inner">2</div>  
  3. </div>  

圖左為旋轉(zhuǎn)前,圖右為旋轉(zhuǎn)后。
2016527121819969.png (500×248)

可以看出圖右就像平時(shí)我們照鏡子在鏡子中的投影一樣。這個(gè)就是元素的背面。
接下來當(dāng)我們在元素inner上加backface-visibility:hidden屬性則元素便會(huì)被隱藏,看起來消失了一樣。如圖
2016527121836783.png (245×246)

相關(guān)文章

最新評論