切圖系列:transform你不知道的那些事

transform 是諸多css3新特性中最打動個人,由於它讓方方正正的box model變得真實了。javascript

transform經過一組函數實現了對盒子大小、位置、角度的2D或者3D變換。不過很長時間內,我對如下問題都想不太明白:css

一、尺寸縮放 scalezoom 變換有何不一樣,爲何被 scale 的盒子裏的內容不會錯位,但 zoom 不是。html

二、位移( transform:translate )與相對定位、絕對定位( position:relative | absolute )有何關係?java

三、在實際項目中發現,位圖(不管是 background-image 仍是 img )在被transform後會模糊掉,尤爲是 scale ;不只如此,在一些網站,好比tmall.com,即便是矢量的svg文件在使用 transform 後,依然模糊了, transform 是否對做用的盒子進行了相似柵格化的操做?css3

四、在實際項目中發現,若是父級元素使用了 transform 且其中的子元素進行了 position:fixed 定位,那麼設置了 position:fixed 的子元素將再也不基於窗口定位。web

五、這種場景暫時未能重現,在chrome下:父級元素使用了 position:fixed ,子元素 <a href=".."></a> 設置了 :hover 僞類、 transition 過渡動畫、並使用javascript動態添加/刪除其class,此時會出現 :hover 樣式失效或添加的class樣式失效且 transition 過渡動畫失效的現象。chrome

等等。express

先說原理吧。

在網上查看了一些大神的博客, transform 是經過一系列矩陣變換完成的,scale等transform-function都是對matrix的封裝,w3c裏沒找到有關說明。對於線性代數裏的東西,博主表示很是小白,其中的數學原理,仍是交給其餘人去解釋吧o(︶︿︶)o canvas

w3c裏的解釋是,transform基於可視化格式模型(visual formatting model,這樣翻譯對不對啊)併爲其繪製出一個座標系,並且全部在這個座標系內進行的操做,如向右向下,都是在這個座標系內以像素方式表示,原文:瀏覽器

The CSS visual formatting model describes a coordinate system within each element is positioned. Positions and sizes in this coordinate space can be thought of as being expressed in pixels, starting in the origin of point with positive values proceeding to the right and down.

那是否是意味着scale縮放,是否只是像素意義上的縮放呢?由此,因縮放致使的svg等矢量內容模糊失真是情理之中了?ಠ_ಠ

我的猜想,應該先轉換成像素,而後進行渲染,這應該和每一個瀏覽器具體渲染過程有關,相關文檔我沒有查,若是有知道的,請給我留言。

要理解transform,還有一個事情要搞清楚,就是visual formatting model,藉助谷歌度娘,找到了w3chelp上的中文版解釋

可視化格式模型是很是抽象的概念。它是 CSS 佈局的核心,經過它,框( box )能夠得到應有的尺寸,放到須要的位置。
咱們一般所看到的頁面都是平面 2D 的效果,但可視化模型倒是 3D 的,除了 X 軸,Y 軸,還有決定元素顯示順序1的 Z 軸。 Z 軸垂直穿過計算機屏幕,面向用戶的一側是正軸,框在 Z 軸方向上離用戶越近,顯示越是靠前。
可視化格式模型的官方說法是,它規定了用戶端在媒介中如何處理文檔樹( document tree )
……

本部分會涉及不少新概念,如包含塊、元素的類型、定位體系、塊級格式化上下文、行內格式化上下文、浮動、絕對定位和 z-index,以及可視化格式模型的細節部分,自動寬度高度的計算等。

博主第一次聽到visual formatting model這個概念,但看了解釋應該知道,這不是一個新概念,姿式水平捉急了ಠ_ಠ

根據這個解釋,元素設置了 transform 並不會改變元素所在的文檔流,其佈局仍然受盒模型支配,所以這裏的變換的效果是能夠與浮動、定位並存的。

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

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

<div style="transform: translate(80px, 80px)">
       <div style="transform: scale(1.5, 1.5)">
            <div style="transform: rotate(45deg)"></div>
       </div>
     </div>
<div style="transform: translate(80px, 80px) scale(1.5, 1.5) rotate(45deg);">
      </div>
  • 座標原點的位置受屬性 transform-origin 的影響。

  • 若是是3D變換,則還會將其加入一個3D渲染上下文(3D rendering context)。根據我的理解,不管有多少個轉換爲3D的元素,其將始終在這個上下文內並可能相互影響,相似一個文檔中的多個被絕對定位的元素。

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

不過,並不意味着和諧,否則怎麼會有那麼多坑問題嘛!(,,Ծ▽Ծ,,)

若是元素由於transform而撐開了父級元素,父級元素會根據自身的 overflow 屬性決定是否出現滾動條、隱藏溢出的部分或是別的什麼。

另外,根據規範,因爲堆疊上下文的建立,該元素會影響其子元素的固定定位:被設置 position:fixed 的子元素將不會基於viewport定位,而是基於這個父元素。

咱們知道,通常狀況下,全部的position值不爲static的元素都會被放到同一個堆疊上下文內(ie不高級瀏覽器不算),也就是說,只存在一個堆疊上下文。而設置了transform的元素則不一樣,因爲它建立了一個新的堆疊上下文,也就是說,其內部被定位的元素的z-index會放在一個徹底獨立的空間內。

可是這個堆疊上下文不包含被定義transform的元素自己,它仍被放在更大的堆疊上下文(若是有的話)裏。

說到這,開篇提到的問題二、4都已經找到答案了,但目前,Chrome還存在一個bug:rendering bug : position:fixed AND -webkit-transform

上面提得另外一個問題重現場景比較麻煩,先不討論了。

留幾個坑回頭填:

  • transform 碰見 display:table | table-row | table-cell

  • 3D渲染上下文是個什麼玩意

  • 陌生又熟悉的 backface-visibility

  • transform 與 css3動畫

  • transform 與 canvas

  • transform 與 svg

艾瑪,那麼多坑,逃 ( ゚Д゚)σ

相關文章
相關標籤/搜索