標籤:
by zhangxinxu from http://www.zhangxinxu.com
本文地址:http://www.zhangxinxu.com/wordpress/?p=2427
一、哥,我被你嚇住了
打架的時候會被塊頭大的嚇住,學習的時候會被奇怪名字嚇住(如“拉普拉斯不等式”)。這與情感化設計本質一致:介面設計好會讓人覺得這個軟體好用!
所以,當看到上面“Matrix(矩陣)”的時候,難免會心生畏懼(即使你已經學過),正常心理。實際上,這玩意確實有點複雜。
然而,這卻是屌絲逆襲的一個好機會。
CSS同行間:
你是不是有這樣的感覺:哎呀呀,每天就是對著設計圖切頁面,貌似技術沒有得到實質性地提升啊,或者覺得日後高度有限!
我們應該都知道二八法則(巴萊多定律),即任何一組東西中,最重要的只佔其中一小部分,約20%,其餘80%的儘管是多數,卻是次要的。如果你有上述的感覺,那你就屬於那80%, 一抓一大把,沒有特色的頁面仔。
CSS門檻低,無需程式基礎或數學邏輯能力,也能做出點自我感覺不錯的東西。然而,你自己也應該清楚的,一般你能輕鬆學到的東西,別人也可以。因此,如果你想擠進那20%的行列,就要學到一般人學不到的深度,學到一般人學不了的東西。自然,是需要更多額外的努力的。如果每次你都比別人努力一點點,何愁不比他人高出幾等。人年輕的時候,貴在堅持!
而這裡的CSS矩陣就是展現你與其他芸芸同行差異的好契機。很多人看到名字就畏懼了,看到奇怪的數學書寫就嚇退了;而你沒有,迎難而上,把搖手機的時間用在理解矩陣上。自然,你就冒尖了一點。類似的,很多其他CSS方面的東西,你也比別人多深入學習一點,怎麼可能就是個普通的頁面仔呢?
因此,從這裡開始,擺脫那80%的行列吧!
偽同行間:
雖然都是從事電腦,雖然都是從事互連網,雖然都是寫代碼的,(據說)寫JAVA的瞧不起寫JavaScript的,寫JavaScript的瞧不起寫CSS的。這可以理解,雖然養雞養鴨成為富翁的不在少數,但是,一說你是農村養雞的,怎麼樣?上海專業的丈母娘們的視線立馬下降60°——被BS了。倒不是因為你是幹農業的,而是“雞”的問題;如果說你是飼養斯裡蘭卡藍孔雀的,得,挑剔的丈母娘們說不定就會正臉看看(唷,斯裡蘭卡,國外貨;唷,孔雀,高檔貨)。
同樣的,如果你掌握的CSS都是些“砌磚頭”的活(雖然砌磚頭也是大學問),被無視也情理之中。但是,矩陣這個東西,就是扭轉乾坤(網稱“逆襲”)的好東西:CSS中也是有複雜的高檔貨的。再忽悠些“圖形演算法、位置計算”之類的詞句,嘿嘿,立馬看法從變成。
二、何為矩陣?
矩陣可以理解為方陣,只不過,平時方陣裡面站的是人,矩陣中是數值:
→
而所謂矩陣的計算,就是兩個方陣的人(可以想象成古代的方陣士兵)相互衝殺。
CSS3中的矩陣
CSS3中的矩陣指的是一個方法,書寫為matrix()
和matrix3d()
,前者是元素2D平面的移動變換(transform),後者則是3D變換。2D變換矩陣為3*3, 如上面矩陣;3D變換則是4*4的矩陣。
有些迷糊?恩,我也覺得上面講述有些不合時宜。那好,我們先看看其他東西,層層漸進——transform
屬性。
具體關於transform
屬性具體內容可以點擊這裡補個課。稍微熟悉的人都知道,transform中有這麼幾個屬性方法:
.trans_skew { transform: skew(35deg); }.trans_scale { transform:scale(1, 0.5); }.trans_rotate { transform:rotate(45deg); }.trans_translate { transform:translate(10px, 20px); }
斜拉(skew),縮放(scale),旋轉(rotate)以及位移(translate)。
那你有沒有想過,為什麼transform:rotate(45deg);
會讓元素旋轉45°, 其後面運作的機理是什麼呢?
下面這張圖可以解釋上面的疑問:
無論是旋轉還是展開什麼的,本質上都是應用的matrix()
方法實現的(修改matrix()
方法固定幾個值),只是類似於transform:rotate
這種表現形式,我們更容易理解,記憶與上手。
換句話說,理解transform
中matrix()
矩陣方法有利於透徹理解CSS3的transform
屬性,這就與那80%的也會應用但只知表象的人拉開了差距!
OK,現在上面提到的CSS3矩陣解釋應該說得通了。
三、矩陣應用情境
雖然題目寫的是“transform
中的Matrix
”,實際上,在CSS3以及HTML5的世界裡,這玩意還是涉獵蠻廣的,如SVG
以及canvas
.
事實上,關於矩陣,我之前曾經介紹過,是在介紹IE瀏覽器下的Matrix矩陣濾鏡的時候說過,IE的濾鏡矩陣與CSS中的矩陣雖然寫法上差異較大,但是,矩陣計算的原來是一致的。只是之前的介紹主要是IE下的旋轉與縮放,同時也不是很深入,因此還有有些局限的。
四、
transform
與座標系統
用過transform
旋轉的人可以發現了,其預設是繞著中心點旋轉的,而這個中心點就是transform-origin
屬性對應的點,也是所有矩陣計算的一個重要依據點(參考自dev.opera.com)。
當我們通過transform-origin
屬性進行設定的時候,矩陣相關計算也隨之發生改變。反應到實際圖形效果上就是,旋轉展開的中心點變了!
舉例來說,如果偶們設定:
-webkit-transform-origin: bottom left;
則,座標中心點就是左下角位置。於是動畫(例片收縮)就是基於圖片的左下角這一點了:
效果可以點擊這裡查看(Chrome瀏覽器)。
再舉個稍微難理解的例子,我們如果這樣設定:
transform-origin: 50px 70px;
則,中心點位置有中間移到了距離左側50像素,頂部70像素的地方(參見),而此時的(30, 30)
的座標為白點所示的位置(這個位置後面會用到)。
仔細看看,是不是很快就理解了哈~~
五、準備好了沒?重頭戲來了
CSS3 transform
的matrix()
方法寫法如下:
transform: matrix(a,b,c,d,e,f);
嚇住了吧,這多參數,一個巴掌都數不過來。好吧,如果你把a~f
這6個參數想象成女神的名詞,你會覺得,世界不過如此嘛~~
實際上,這6參數,對應的矩陣就是:
注意書寫方向是豎著的。
上面提過,矩陣可以想象成古代計程車兵方陣,要讓其發生變化,只有與另外一個士兵陣火拚就可以了,即使這是個小陣。
反應在這裡就是如下轉換公式:
其中,x
, y
表示轉換元素的所有座標(變數)了。那後面的ax+cy+e
怎麼來的呢?
//zxx:大學時候線性代數知識,懂的人這裡可以直接跳過
很簡單,3*3矩陣每一行的第1個值與後面1*3的第1個值相乘,第2個值與第2個相乘,第3個與第3個,然後相加,如同色標註:
那ax+cy+e
的意義是什嗎?
記住了,ax+cy+e
為變換後的水平座標,bx+dy+f
表示變換後的垂直位置。
又迷糊了?不急,一個簡單例子就明白了。
假設矩陣參數如下:
transform: matrix(1, 0, 0, 1, 30, 30); /* a=1, b=0, c=0, d=1, e=30, f=30 */
現在,我們根據這個矩陣位移元素的中心點,假設是(0, 0)
,即x=0
, y=0
。
於是,變換後的x
座標就是ax+cy+e = 1*0+0*0+30 =30
, y
座標就是bx+dy+f = 0*0+1*0+30 =30
.
於是,中心點座標從(0, 0)
變成了→(30, 30)
。對照上面有個(30, 30)
的白點圖,好好想象下,原來(0,0)
的位置,移到了白點的(30, 30)
處,怎麼樣,是不是往右下方同時位移了30像素哈!!
實際上transform: matrix(1, 0, 0, 1, 30, 30);
就等同於transform: translate(30px, 30px);
. 注意:translate
,rotate
等方法都是需要單位的,而matrix
方法e, f
參數的單位可以省略。
一例勝萬語,您可以狠狠地點擊這裡:matrix(1,0,0,1,30,30)執行個體demo
在現代瀏覽器下,會有類似下面動圖的效果:
效果只是表象的,我想到了一個更好的idea去表現矩陣到底是如何變換的,您可以狠狠地點擊這裡:matrix分解變換示範
為了提高效能,demo中每個單元分解成了5px * 5px
的地區。示範分兩步,先是示範每個單元的位置是如何計算的,接著動畫表現其位置的位移。
這個demo所做的工作就是把瀏覽器瞬間完成的計算和渲染變成了可控的分步顯示,這樣,大家就可以很直觀地看出,這個矩陣計算到底是如何起作用的。為正在示範過程中的:
//zxx:由於預設100毫秒間隔不斷渲染,因此如果你電腦CPU或是瀏覽器hold不住,可以取消“自動示範”的勾選,然後,點擊左邊的按鈕手動分步查看。
總結
聰明的你可能以及意識到了,尼瑪matrix表現位移就是:
transform: matrix(與我無關, 哪位, 怎麼不去高考, 打麻將去吧, 水平位移距離, 垂直位移距離);
你只要關心後面兩個參數就可以了,至於前面4個參數,是牛是馬,是男是女都沒有關係的。
六、transform matrix矩陣與縮放,旋轉以及展開
位移是matrix效果中最簡單,最容易理解的,因此,上面很詳盡地對此進行展開說明。下面,為了進一步加深對matrix的理解,會簡單講下matrix矩陣與縮放,旋轉以及展開效果。
縮放(scale)
上面的位移只要關心最後兩個參數,這個縮放也是只要關心兩個參數。哪兩個呢?
如果你足夠明察秋毫,應該已經知道了,因為上面多次出現的:
transform: matrix(1, 0, 0, 1, 30, 30);
已經出賣了。
發現沒,matrix(1, 0, 0, 1, 30, 30);
的元素比例與原來一樣,1:1, 而這幾個參數中,有兩個1
, 啊哈哈!沒錯,這兩個1
就是縮放相關的參數。
其中,第一個縮放x
軸,第二個縮放y
軸。
用公式就很明白了,假設比例是s
,則有matrix(s, 0, 0, s, 0, 0);
,於是,套用公式,就有:
x‘ = ax+cy+e = s*x+0*y+0 = s*x;
y‘ = bx+dy+f = 0*x+s*y+0 = s*y;
也就是matrix(sx, 0, 0, sy, 0, 0);
,等同於scale(sx, sy)
;
好了,至此,無需多說了……
眼見為實,因此demo還是要滴,您可以狠狠地點擊這裡:matrix矩陣與縮放demo
為了避免元素比例放大時候遮蓋上面的文字框以及描述位子,因此,將元素的座標原點遷至了左上方。
旋轉(rotate)
旋轉相比前面兩個要更進階些,要用到(可能勾起學生時代陰影的)三角函數。
方法以及參數使用如下(假設角度為θ
):
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θ
這個與IEMatrix濾鏡中的旋轉是有些類似的(M11表示矩陣第1行第1個(參數a),M21表示矩陣第2行第一個(參數b)……):
filter:progid:DXImageTransform.Microsoft.Matrix(M11=cosθ,M21=sinθ,M12=-sinθ,M22=cosθ‘);
哎呀呀,四個參數,我記不住啊!莫慌,我們可以這樣子記憶:
CS-SC:初三-上床,對稱結構,這下忘不了了吧~~
您可以狠狠地點擊這裡:transform matrix矩陣與旋轉demo
不過,說句老實話,就旋轉而言,rotate(θdeg)
這種書寫形式要比matrix
簡單多了,首先記憶簡單,其次,無需計算。例如,旋轉30°,前者直接:
transform:rotate(30deg);
而使用matrix
表示則還要計算cos
, sin
值:
transform: matrix(0.866025,0.500000,-0.500000,0.866025,0,0);
展開(skew)
展開也用到了三角函數,不過是tanθ
,而且,其至於b, c
兩個參數相關,書寫如下(注意y
軸傾斜角度在前):
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
對應於skew(θx + "deg",θy+ "deg")
這種寫法。
其中,θx
表示x
軸傾斜的角度,θy
表示y
軸,兩者並無關聯。
還是靠執行個體說話吧,您可以狠狠地點擊這裡:matrix矩陣與展開demo
在Chrome下可以很動態地查看不同傾斜角度對應的展開的效果:
七、既然有簡單的skew, rotate..,那matrix有何用?
我想有人會奇怪,既然CSS3 transform中提供了像skew
, rotate
, …
效果,那還需要掌握和熟悉讓人頭大的矩陣方法幹嘛呢?
好問題,確實,對於一般地互動應用,transform
屬性預設提供的些方法是足夠了,但是,一些其他的效果,如果transform
屬性沒有提供介面方法,那你又該怎麼辦呢?比方說,“鏡像對稱效果”!
沒轍了吧,這是,就只能靠matrix
矩陣了。要知道,matrix矩陣是transform
變換的基礎,可以應付很多高端的效果,算是一種進階應用程式技巧吧。掌握了基礎,才能兵來將擋水來土掩啊。
OK,這裡就示範下,如何使用CSS3 transform
matrix
矩陣實現鏡像效果。
這個有點難度,因此,我們先看demo,您可以狠狠地點擊這裡:matrix與鏡像對稱效果demo
框框中輸入旋轉的角度值(用來確定鏡像的對稱軸),然後失去焦點,就會呈現出對應的鏡像對稱效果了:
您可以在FireFox或是Chrome等瀏覽器上體驗下matrix
實現的鏡像漸層效果。
demo頁面中的一個軸是為了便於理解我加上的效果,實際上,在鏡像對稱的時候軸是看不見的。
軸圍繞的那個點就是CSS3中transform
變換的中心點,自然,鏡像對稱也不例外。因為該軸永遠經過原點,因此,任意對稱軸都可以用y = k * x
表示。則matrix
表示就是:
matrix((1-k*k) / (1+k*k), 2k / (1 + k*k), 2k / (1 + k*k), (k*k - 1) / (1+k*k), 0, 0)
這個如何得到的呢?
啊,高中數學來了,就當再高考一次吧,如,已經y=kx
,並且知道點(x, y)座標,求其對稱點(x’, y’)的座標?
很簡單,一是垂直,二是中心點在軸線上,因此有:
(y-y‘) / (x - x‘) = -1/ k → ky-ky‘ = -x+x‘
(x + x‘) / 2 * k = (y + y‘)/2 → kx+kx‘ = y+y‘
很簡單的,把x‘
和y‘
提出來,就有:
x‘ = (1-k*k)/(k*k+1) *x + 2k/(k*k+1) *y;
y‘ = 2k/(k*k+1) *x + (k*k-1)/(k*k+1) *y;
再結合矩陣公式:
x‘ = ax+cy+e;
y‘ = bx+dy+f;
我們就可以得到:
a = (1-k*k)/(k*k+1);
b = 2k/(k*k+1);
c = 2k/(k*k+1);
d = (k*k-1)/(k*k+1);
也就是上面matrix方法中的參數值啦!
為自己計算的草稿:
八、3D變換中的矩陣
3D變換雖然只比2D多了一個D,但是複雜程度不只多了一個。從二維到三維,是從4到9;而在矩陣裡頭是從3*3變成4*4, 9到16了。
其實,本質上很多東西都與2D一致的,只是複雜度不一樣而已。這裡就舉一個簡單的3D縮放變換的例子。
對於3D縮放效果,其矩陣如下:
代碼錶示就是:
transform: matrix3d(sx, 0, 0, 0, 0, sy, 0, 0, 0, 0, sz, 0, 0, 0, 0, 1)
您可以狠狠地點擊這裡:matrix3d下的3D比例變換demo
補充於2013-04-24
關於3D變換,可以參見邪惡的這篇文章:“CSS3 3D transform變換,不過如此!”
九、結束語
想了想,沒什麼要嘮叨的。文中觀點若是存在疑問或不準確的,歡迎指正。感謝閱讀!
參考文章:
Understanding the CSS Transforms Matrix
CSS3前端開發中需要用到的變換矩陣
原創文章,轉載請註明來自張鑫旭-鑫空間-鑫生活[http://www.zhangxinxu.com]
本文地址:http://www.zhangxinxu.com/wordpress/?p=2427
(本篇完)
理解CSS3 transform中的Matrix(矩陣)——張鑫旭