CSS3中transform變換模型渲染的解析

來源:互聯網
上載者:User
這篇文章主要介紹了關於CSS3中transform變換模型渲染的解析,有著一定的參考價值,現在分享給大家,有需要的朋友可以參考一下

transform通過一組函數實現了對盒子大小、位置、角度的2D或者3D變換,這裡我們主要來深入解讀CSS3中transform變換模型的渲染,尤其是關注web端3D渲染動畫的朋友千萬不要錯過

介紹

transform是通過一系列矩陣變換完成的,scale等transform-function都是對matrix的封裝。

w3裡的解釋是,transform基於可視化格式模型(visual formatting model,這樣翻譯對不對啊)並為其繪製出一個座標系,而且所有在這個座標系內進行的操作,如向右向下,都是在這個座標系內以像素方式表示

元素設定了transform並不會改變元素所在的文檔流,其布局仍然受盒模型支配,因此這裡的變換的效果是可以與浮動、定位並存的。

當元素設定了transform後,會為該元素定義一個座標系,並且在該座標系內進行矩陣變換,將變換結果映射到使用者座標系(也就是實際上的上下文)中。

多個矩陣變換函數將依次從左至右計算,如transform:translate(80px, 80px) scale(1.5, 1.5),瀏覽器會先計算位移,再縮放1.5倍。以下兩種代碼效果相同:

html

<p style="transform: translate(80px, 80px)">     <p style="transform: scale(1.5, 1.5)">          <p style="transform: rotate(45deg)"></p>     </p>   </p>

html

<p style="transform: translate(80px, 80px) scale(1.5, 1.5) rotate(45deg);">    </p>

座標原點的位置受屬性 transform-origin的影響。

如果是3D變換,則還會將其加入一個3D渲染上下文(3D rendering context)。根據個人理解,無論有多少個轉換為3D的元素,其將始終在這個上下文內並可能相互影響,類似一個文檔中的多個被絕對位置的元素。

任何非none的transform值都會導致一個堆疊上下文(stacking context)和包含塊(containing block)的建立。

變換渲染模型
為transform屬性指定一個除了none的值便會在元素上建立一個新的局部座標系統並且應用於這個元素。通過元素的變換模型,元素可以繪製渲染出自己的座標系統。變換是可以積累的。也就是說,元素可以通過父元素的座標的系統來建立自己的局部座標系統。從使用者的視角看,一個元素不但可以從它的祖先元素上有效積累transform屬性,而且也可以給自己增加transform屬性並應用與自己。這些變換的積累為元素描繪出了當前的變換模型。

帶有兩個軸的座標空間:X軸水平向右為正,Y軸垂直向下為正。立體的變換函數增加了座標空間將其延生至了三維空間,增加的Z軸垂直與螢幕,並且面向觀察者的方向為正(也就是電腦螢幕前的我們)。。

變換模型通過如下的transform和transform-origin屬性進行計算

從具體的模型開始
通過transfrom-origin的X,Y,Z計算值進行移動
從左至右複合應用在transform屬性中的transform functions
使之前設定的transform-origin的值無效並進行移動
EXAMPLE1

p {     transform: translate(100px,100px);   }


EXAMPLE2

p {     height: 100px;     width: 100px;     transform-origin: 50px 50px;     transform:rotate(45deg)   }

transform-origin通過在X,Y軸方向上各移動50px來移動原點。元素沿著原點順時針旋轉了45°。當所有的transform functions都應用後,平移後的原點在X,Y軸上又各移動了-50px,回到了原來的位置。

理解
上面的話的意思就是,transform-origin的起始點是在原點的位置,旋轉圍繞著transform-origin在轉,移動transform-origin是從原點開始的,而不是transform-origin的預設位置開始移動的(預設為元素中心,上例恰好也剛剛好移動到元素的中心位置),transform-origin移動完後,並在元素上已經將transform functions應用完後,平移後的原點便會回到原來的位置,也就是說,下次改變transform-origin的位置仍然是從起始點算起(也就是之前的原點)。

EXAMPLE3
以下所涉圖片深綠色部分均是沒有使用變換屬性時元素的本來樣子。

p {     height: 100px;     width: 100px;     transform: translate(80px,80px) scale(1.5,1.5) rotate(45deg);   }

首先在X,Y軸上各移動80px,然後將元素放大150%,接著沿著Z軸方向順時針旋轉45°。

注意:縮放和旋轉,都是通過元素的中心進行運轉的,因為元素的預設transfrom-origin值為50% 50%。

通過嵌套元素可以實現與上面相同的效果

<p style="transform: translate(80px, 80px)">    <p style="transform: scale(1.5, 1.5)">        <p style="transform: rotate(45deg)"></p>    </p>  </p>

3D變換渲染
通常,元素都是依照平面進行渲染,並且被渲染的元素與它們的包含塊的平面一致。平面的transform functions可以改變元素的表現,但是它仍然在與它的包含塊相同的平面裡進行渲染。

三維的變換會導致變換模型有著一個非0的Z組件(Z軸投射在螢幕的外面)。這樣可以造成元素可以在不同的平面進行渲染,而不是在它的包含塊的平面內進行渲染。這也可能會影響一個元素和與之有聯絡的另一個元素從前到後的渲染順序,同時和導致與其他元素髮生交叉。這樣的表現依賴於這個元素是否為3D rendering context中的一員,正如下所說

上面的描述並不會完全準確的在WebKit中是實現。也許它會被改變來適應現在的是實現?See,Bug 19637
EXAMPLE4

p {     height: 150px;     width: 150px;   }   .container {     border: 1px solid black;     background-color: #ccc;   }   .transformed {     transform: rotateY(50deg);     background-color: blue;   }

<p class="container">    <p class="transformed"></p>  </p>


這次變換是一個圍繞著垂直的Y軸進行的50度旋轉。但是為什麼這次變換為什麼使的盒子便窄了呢?而不是變得立體呢?

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

用圖形解釋了縮放比例是如何依賴於perspective屬性和Z的值。在上面的那張圖,Z值是d的一半。原始的圓圈(實線圓圈)出現在Z上(虛線圈),為了是它呈現在畫面中,圓圈通過以上兩個要素按比例放大,最後在畫面中呈現出來了放大的淺藍色圓圈。下面的圖形,圓圈通過比例進行縮小出現在原始位置後面的1/3圓圈,最後在畫面中呈現出了縮小的淺藍色圓圈。

通常假設觀察者眼睛的位置在畫面的中央。但是,如果想的話,這個位置也是可以移動的-例如,如果一個網頁包含了很多圖畫那麼大家通過設定perspective-origin的值來分享相同的視角。

圖形表現了向上移動perspective origin對錶現效果的影響

透視模型按如下進行計算:

1.從具體的模型開始
2.通過 設定的perspective-origin的X,Y的計算值進行移動
3.通過獲得perspective屬性的值應用在模型上
4.使之前設定的perspective- origin的值無效並進行移動
EXAMPLE5
這個例子表現了透視可以被用來表達立體的變換從而顯現出更多真實的細節

p {     height: 150px;     width: 150px;   }   .container {     perspective: 500px;     border: 1px solid black;     background-color: #ccc;   }   .transformed {     transform: rotateY(50deg);     background-color: blue;   }

<p class="container">    <p class="transformed"></p>  </p>


裡面的元素和在前面的例子中有著相同的變換,但是它的渲染被父元素上的perspective屬性所影響。透視給予了一個顯現的深度,導致頂點有了Z座標(靠近觀察者)使其在X,Y軸被放大,並且更進一步的(在負的Z軸上)也會被縮小。
一個並不包含在3D渲染上下文中的立體變換元素有著合適的transform值進行渲染,但是也不會與其他任何元素髮生相交。在這個EXAMPLE4中的立體變換可以被考慮為一種繪畫效果,就像平面中的變換。相似的,變換不會影響渲染命令。舉個例子,在transform中設定Z的值使元素進行移動可能使元素變得更大,但是並不會導致元素去渲染它前面沒有設定Z值的元素

一個包含在3D渲染內容相關的立體變換元素在同樣的3D渲染上下文中可以與其他元素相交;參與相同3D渲染內容相關的元素,根據它們的變換結果,可能會互相隱藏或者相交。在同樣的3D座標空間擺放,使它們好像全部都是兄弟姐妹。一個元素在立體空間中擺放的位置決定於從建立3D渲染內容相關的包含塊中積累的變換模型所決定。
EXAMPLE6

p {     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;   }

<p class="container">     <p class="transformed">       <p class="child"></p>     </p>   </p>


這個例子表現了嵌套的3D變換元素在缺少transform-style: preserve-3d時是如何渲染的。藍色的p和之前的例子變換結果是一樣的,都是被父元素的perspective屬性所影響。綠黃色的元素同樣有繞著X軸進行旋轉的3D變換。然而,綠黃色元素在它的父元素所在平面進行渲染因為他不是3D渲染上下文中的一員;父元素是二維的。
按照如下規則,元素可建立並參與在3D渲染上下文中:

3D渲染上下文通過有著transform-style: preserved-3d值的變換元素建立並且它自己並不是3D渲染上下文中的一員。這樣的元素通常都是一個包含塊。一個元素建立3D渲染上下文同樣也參與其中。
一個有著transform-style: preserved-3d值的元素,參與在它自己建立的3D渲染上下文中,擴大了3D渲染上下文,而不是建立了一個新的3D渲染上下文。
一個元素參與3D渲染上下文,除非它的包含塊建立了3D渲染上下文或者擴充了3D渲染上下文
最後的變換結果通常是在3D渲染上下文中渲染的元素3D變換模型的積累,如下:

從具體的模型開始
對於每一個在3D變換根項目和元素之間的包含塊,考慮以下幾點:
1.在元素的包含塊上積累perspective matrix(如果可以的話)。包含塊並不一定要成為3D渲染上下文中的一員
2.元素的offset-parent是相對於它的包含塊的,元素應用計算後的移動值等同於垂直水平移動。
3.累加變換效果
EXAMPLE7

p {     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;   }

這個例子和前面的例子是相同的,除了加了一個transform-style: preserve-3d值在藍色的元素上。藍色的元素建立的3D渲染上下文,綠黃色元素是其中一員。現在藍色和綠黃色元素都被容器中的perspective所影響,並且同時分享了一個相同的立體空間,所以淺綠色的元素在它的父元素上擺動。

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

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

在3D渲染上下文裡,在應用完積累的變換後,沒有相交的元素的渲染順序基於在Z軸上的位置。元素在Z軸的位置相同則渲染順序由層疊上下文決定。
EXAMPLE8

p {    width: 150px;   }   .container {    height: 145px;    background-color: rgba(0,0,0,0.3);    border: 1px solid black;    transform-style: preserve-3d;    perspective: 500px;   }   .container>p {    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;   }

<p class="container">    <p></p>    <p></p>  </p>

這個例子展示了,在3D渲染上下文中元素是可以相交的。容器元素為自己建立了3D渲染上下文並且他有兩個子項目。子項目互相相交,同時橘黃色的元素也與容器相交。

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

理解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);//旋轉180   }
<p class="wrap">    <p class="inner">2</p>  </p>

圖左為旋轉前,圖右為旋轉後。

可以看出圖右就像平時我們照鏡子在鏡子中的投影一樣。這個就是元素的背面。
接下來當我們在元素inner上加backface-visibility:hidden屬性則元素便會被隱藏,看起來消失了一樣。

以上就是本文的全部內容,希望對大家的學習有所協助,更多相關內容請關注topic.alibabacloud.com!

相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.