理解CSS3 transform中的Matrix(矩阵)
一、哥,我被你嚇住了
打架的時候會被塊頭大的嚇住,學習的時候會被奇怪名字嚇住(如“拉普拉斯不等式”)。這與情感化設計本質一致:界面設計好會讓人覺得這個軟件好用!
所以,當看到上面“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表現偏移就是:
你只要關心后面兩個參數就可以了,至于前面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軸傾斜角度在前):
套用矩陣公式計算結果為:
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' → 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(矩阵)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CSS3实例教程:border-imag
- 下一篇: Java静态变量与静态方法与成员变量成员