想寫寫關於矩陣變換的博文已經想了好久了,今天看到 winter 寫的一篇博客CSS3:transform與transition背後的數學原理,因而就促成了本文。注意,下面的演示內容須要現代瀏覽器支持。好比Chrome/Firefox/Opera。閱讀器中沒法看到演示。前端
矩陣是線性代數中的內容,在計算機圖形學中就拿來作矩陣變換。在之前,對於前端工做來講,幾乎用不到矩陣變換。然而,隨着瀏覽器的進步,HTML5和CSS3的普及,對於前端能夠操做的東西愈來愈多,因而,矩陣變換也出如今視野當中了。web
矩陣變換,聽起來是一個挺高級的東西,其實本質上只不過是把一系列簡單的數學運算給包裝一下,賦予一個比較華麗和高深的外表而已。若是你以前沒有接觸過矩陣運算,也不用慌,跳過下面矩陣公式,直接看每條後面的黑體字公式便可。這些公式僅僅涉及高中水平的加減運算和三角函數而已。除了最開始的時候我會搬出那個矩陣,以後的討論我會避開矩陣的公式,直接用容易理解的方式闡述問題。算法
最先瀏覽器中支持的矩陣變換多是在SVG的標準中。以後跟圖形帶點邊的CSS 3以及HTML5的Canvas中也有了矩陣變換,固然強大的Flash以及Flex中也有變換矩陣。他們的基本原理都是同樣的。目前2D的矩陣變換已經有很多瀏覽器支持了,而3D的變換還需時日。瀏覽器
說了半天矩陣變換,其實本質上來講,一個元素渲染後就能夠獲得一張位圖,而後對這個位圖上每一點進行變換,就能夠獲得新的一張位圖,從而產平生移、縮放、旋轉,切變以及鏡像反射等效果了。函數
目前不管是SVG也好,CSS 3也好,仍是Canvas,2D的矩陣變換都提供了6個參數a b c d e f,其使用基本公式是這樣的:spa
其中,x和y是元素最開始的座標,x’ 和y’則是經過矩陣變換後獲得新的座標。
經過中間的那個3×3的變換矩陣,對原先的座標施加變換,就能獲得新的座標了。orm
注意!a b c d e f幾個參數的排列方式,是豎着排的,網上有很多文章排列方向有誤。博客
根據矩陣乘法的運算法則,上面的矩陣式子能夠化成下面的兩個式子數學
x’=ax+cy+e
y’=bx+dy+fit
也就是說,別看上面有那麼一大坨的東西,本質上就是上面這兩條簡簡單單的公式而已。以後的討論中,我將圍繞着上面的兩行來討論,而再也不涉及矩陣的內容了。
若是調用時提供參數matrix(1,0,0,1,tx,ty),即a=d=1,b=c=0,那麼上面的式子就簡化成
x’ = 1x+0y+tx = x+tx
y’ = 0x+1y+ty = y+ty
很容易看到,這裏就是在原先x,y的基礎上進行平移,變成x+tx,y+ty點而已。很是簡單。若是數學上講,tx和ty就比如是Δx和Δy。
x’ = x+Δx
y’ = y+Δy
CSS 3中的transform: translate(tx, ty);就等價於transform: matrix(1,0,0,1,tx,ty);注意,使用matrix的時候不須要單位,默認是px,而translate須要單位,能夠是px、em之類的單位。
若是調用時提供參數matrix(Sx,0,0,Sy,0,0),即a或d不等於1,好比a=Sx,d=Sy而b=c=e=f=0,因而公式簡化成
x’ = Sx*x+0y+0 = Sx*x
y’ = 0x+Sy*y+0 = Sy*y
能夠想到,這個操做,其實是讓x的座標擴大Sx倍,而y的座標擴大Sy倍。
這主要是用來讓元素進行縮放效果的。若是Sx和Sy大於1,則是放大,而Sx和Sy小於1,就是縮小了,若是等於1,那就是保持原狀了。而且,因爲x方向和y方向是相互獨立的,因此能夠一個方向放大,另外一個方向縮小。
上面的那個例子中,我設置的m和n都是0.5,因而圖形長寬就各縮小了一半。另外,值得注意的是,他是以元素的中心做爲縮放的基點的,而不是左上角。
CSS 3中的transform: scale(Sx, Sy);就等價於transform: matrix(Sx,0,0,Sy,0,0);
這裏用到的就相對高級一些了,須要使用三角函數的一些知識了
若是調用時提供參數matrix(cosθ,sinθ,-sinθ,cosθ,0,0)
x’ = x*cosθ-y*sinθ+0 = x*cosθ-y*sinθ
y’ = x*sinθ+y*cosθ+0 = x*sinθ+y*cosθ
因爲計算機圖形學中,一般向右爲x軸正方向,向下爲y軸正方向,因此這裏的θ表示元素繞座標原點順時針旋轉的角度。而這裏的原點不是元素的左上角,而是元素的中心點。
上面的例子中,我把一個div順時針旋轉了37°,cos37°=0.8,sin37°=0.6,因此提供的矩陣的參數就是 matrix(0.8,0.6,-0.6,0.8,0,0)
CSS 3中,transform:rotate(37deg)就等價於我上面的那個變換了。注意CSS 3中的角度必須帶單位 deg。好處是不用本身算sin和cos值了。
切變,就是把一個元素往某一個方向傾斜必定的角度。傳入的參數應當是matrix(1,tan(θy),tan(θx),1,0,0)
x’ = x+y*tan(θx)+0 = x+y*tan(θx)
y’ = x*tan(θy)+y+0 = x*tan(θy)+y
這裏的θx和θy分別表明往x正方向和往y正方向傾斜的角度,二者是相互獨立的。上面的例子中,我把元素往x方向傾斜了45°,所以他的tan(θx)=1
CSS 3中的transform: skew(θx, θy);就等價於transform: matrix(tan(θx),0,0,tan(θy),0,0); 若是使用skew的話,直接使用角度便可,但必須帶單位deg,好比上面的例子用矩陣的話寫成transform: matrix(1,0,1,1,0,0);等價於 transform: skew(45deg, 0);
鏡像反射就是指元素對某一條直線作鏡像對稱。最基本的狀況是能夠對通過原點的某條直線進行反射。定義(ux,uy)爲直線方向的單位向量。也就是說,若是直線方程是y=kx,那麼ux=1/sqrt(1+k^2),uy=k/sqrt(1+k^2)
那麼對這種鏡像反射變化時傳入的參數應當是
matrix(2*ux^2-1,2*ux*uy,2*ux*uy,2*uy^2-1,0,0)
因而最終的方程
x’ = (2*ux^2-1)*x+2*ux*uy*y
y’ = 2*ux*uy*x+(2*uy^2-1)*y
上面的例子中,就是對y=2x這條直線進行的鏡像對稱。CSS 3中目前沒有簡化的規則與之對應。
至於如何對一條不過原點的線對稱,則須要設置原點所在的座標了。因爲默認狀況下,原點座標是這個元素的中心,若是改變了原點的座標,就能夠改變對稱的直線,固然也能夠改變前面全部效果的呈現方式,CSS 3中使用transform-origin方法修改座標原點的位置。
最後,若是你想要玩的更High點,買本計算機圖形學的書來看是不可避免的,這篇文章也僅僅是個皮毛而已。但願對你有所幫助。