特效屬性「Transform」+ 矩陣 matrix

CSS門檻低,無(wú)需程序基礎(chǔ)或數(shù)學(xué)邏輯能力,也能做出點(diǎn)自我感覺(jué)不錯(cuò)的東西。然而,你自己也應(yīng)該清楚的,一般你能輕松學(xué)到的東西,別人也可以。因此,如果你想擠進(jìn)那20%的行列,就要學(xué)到一般人學(xué)不到的深度,學(xué)到一般人學(xué)不了的東西。自然,是需要更多額外的努力的。如果每次你都比別人努力一點(diǎn)點(diǎn),何愁不比他人高出幾等。人年輕的時(shí)候,貴在堅(jiān)持!CSS中也是有復(fù)雜的高檔貨,transform中的矩陣matrix就是其中典型一個(gè)。

? Transform 是CSS極為關(guān)鍵且復(fù)雜的一個(gè)屬性,功能豐富而且強(qiáng)大,能方便解決很多平常難以處理的問(wèn)題,但她本身有些學(xué)習(xí)難度,如果你對(duì)頁(yè)面效果愛(ài)的深沉,也請(qǐng)你對(duì)她愛(ài)的深沉。

# Transform的值大類

? transform 本質(zhì)上來(lái)說(shuō)是一系列的變形函數(shù),主要有以下值:

  1. none - 不進(jìn)行轉(zhuǎn)換,常用作覆蓋別的值使用
  2. translate(x,y) - 2d位移;translate3d(x,y,z) - 3d位移; transformX/Y/Z(n) - 單向位移
  3. scale(x,y) - 2d縮放; scale3d(x,y,z) - 3d縮放; scaleX/Y(n) - 單向縮放
  4. rotate(angle) - 2d旋轉(zhuǎn); rotate3d(x,y,z,angle) - 3d旋轉(zhuǎn);rotateX/Y/Z(angle) - 單向旋轉(zhuǎn)
  5. skew(x-angle,y-angle) - 傾斜變換; skewX/Y(angle) - 單向傾斜變換
  6. matrix[3d] - 矩陣
  7. perspective(n) - 視距(值)
    ?

# Transform的前置屬性

  1. transform-origin - 變換原點(diǎn)
  2. transform-style - 變換類型
  3. perspective - 3d透視視圖的視距(屬性)
  4. perspective-origin - 視距的基點(diǎn)
  5. backface-visibility - 是否可以看見(jiàn)舞臺(tái)背面

? 看到這里是不是已經(jīng)快頭暈了?是否開(kāi)始懷疑你以前知道的是假的 transform ?如果你看到你不熟悉或不會(huì)的,沒(méi)關(guān)系,好好看,本文會(huì)給你細(xì)細(xì)道來(lái)。
?

# 位移 - transform: translate(x,y)

? trnaslate2d位移系列,主要有:translate(x[,y]), translateX(x), translateY(y), translateZ(z), translate3d(x,y,z)

? translate(x[,y]) 當(dāng)參數(shù)設(shè)置為正數(shù)時(shí)表示正向移動(dòng),負(fù)數(shù)為反向移動(dòng),類似于 position:relative + margin;這里注意,y值的設(shè)置是可以省略的,與margin、padding 省略值后表示兩者值一致不同的是,如果省略了y,則表示y的值為0。例:translate(50px)translate(50px,0) 表示沿x軸向右移動(dòng)50個(gè)像素,y軸不變。

? 如果要使用 translate(x,y) ,最好不要省略參數(shù),如果只需要偏移一個(gè)方向,建議使用 translateX()translateY() ;關(guān)于 translate(x,y),我有一個(gè)很經(jīng)典的案例分享給大家:按鈕實(shí)現(xiàn)上下左右絕對(duì)居中(不受文字字號(hào)影響)

<div>
    <font>這里是文案</font>
</div>
div {
  position: relative;
}
font {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
? translate3d位移主要有:translate3d(x,y,z), translateZ(z)

? 先說(shuō)簡(jiǎn)單的,translateZ(z) 是指在z軸方向上的位移效果,直白點(diǎn)說(shuō)就是圖像距離看官的距離關(guān)系,距離越近,圖像就越大;舉個(gè)例子如 看遠(yuǎn)處的山比看近處的手指還小。
? 到這里必須要提前提到另一個(gè)屬性:視距 perspective - 表示看官眼睛的位置;當(dāng) translate 值超過(guò)視距時(shí),圖像就消失了,就好比圖像移動(dòng)到看官眼睛后面一樣,這個(gè)大家應(yīng)該都能理解。我們用代碼來(lái)說(shuō)話(省去不相關(guān)屬性):

<div>
  <p></p>
</div>
div {
  width: 100px;
  height: 100px;
  perspective: 100px; 
}
p {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  transform: translateZ(75px);
}

注意坑】要使用translateZ,必須在父元素上設(shè)置perspective


案例中我們可以看出,我們只設(shè)置了30px的寬高,但因?yàn)樵O(shè)置了圖像向前移動(dòng) (75/100)% , 因此,圖像變大變近了。大家應(yīng)該能感覺(jué)的出來(lái),綠圓在白色成的前面。(!好吧,我問(wèn)了身邊的女士,她說(shuō)沒(méi)感覺(jué))

? 會(huì)了translareZ(z) 之后,translate3d(x,y,z)` 也就簡(jiǎn)單了,無(wú)非就是在做Z位移的同時(shí)做了x,y的位移;把剛才的例子稍作修改后直接上代碼:

transform: translate3d(5px,5px,75px);


一個(gè)引申】看完也許你會(huì)問(wèn),如果 translate(x,y)position:relative 類似,為什么不用后者呢?簡(jiǎn)單好記。說(shuō)的也不算全錯(cuò),畢竟有使用場(chǎng)景。但,前者有幾點(diǎn)后者無(wú)法達(dá)到的優(yōu)勢(shì),而且很關(guān)鍵。

  1. 如果是動(dòng)畫效果,translate能達(dá)到比1px更小的過(guò)渡效果,而后者卻不行,這就影響了用戶體驗(yàn);
  2. translate的動(dòng)畫效果能啟用電腦GPU加速,分離圖層,大大減少頁(yè)面重繪模塊,節(jié)省資源。
  3. position 的可拓展性不如 translate等。
    ?

# 縮放 - transform: scale(x,y)

? scale2d縮放系列,主要有:scale(x,y), scaleX(x), scaleY(y)

? scale(x[,y]) 允許省略y,當(dāng)省略y時(shí)表示x,y等值縮放。如果只想縮放x或y軸,可以使用 scaleX(x), scaleY(y) 。既然為縮放,傳遞的參數(shù)肯定為縮放比例,也就是說(shuō),約定 1 為大小不變,0.01~0.99 表示縮小,>1 表示放大。
? 例:scale(0.5) 等同于 scale(0.5, 0.5); scaleX(0.5) 等同于 scale(0.5, 1)

? 還有一個(gè)特例,如果我們設(shè)置縮放比例為負(fù)數(shù)會(huì)怎么樣?一起來(lái)看一下效果:

transform: scale(-1);
transform: scale(-1.5);

所以說(shuō),設(shè)置負(fù)數(shù),可以使圖像翻轉(zhuǎn),縮放規(guī)則與正數(shù)一致。

? scale3d縮放系列,有:scale3d(x,y,z) , scaleZ(z)

? 所謂3d縮放,就是在z軸上也有縮放效果,但只有在z軸上有分內(nèi)容時(shí)才能生效(其實(shí)x,y軸也一樣,只是x,y軸上的直觀容易理解些)

? scale3d的第三個(gè)參數(shù),比位移的第三個(gè)參數(shù)可難以理解多了。拋開(kāi)其他因素,我們先來(lái)研究scaleZ(z)。因?yàn)樗且粋€(gè)3d變形效果,因此同 translateZ(z) 一致,我們需要為其創(chuàng)建一個(gè)3d環(huán)境,這里把translateZ一起加進(jìn)來(lái)對(duì)比討論。

<div class="perspective">Translated</div>
<div>Normal</div>
<div class="scaled">Scaled</div>
div {
  display: inline-block;
  width: 80px;
  height: 80px;
  background-color: skyblue;
}
.perspective {
  /* Includes a perspective to create a 3D space */
  transform: perspective(400px) translateZ(-100px);
  background-color: cornsilk;
}
.scaled {
  /* Includes a perspective to create a 3D space */
  transform: perspective(400px) scaleZ(2);
  background-color: pink;
}


? 你應(yīng)該和我一開(kāi)始感覺(jué)一樣,在想,為什么設(shè)置了 scaleZ(2) 但粉色塊一直不動(dòng)呢?試試你會(huì)發(fā)現(xiàn),參數(shù)設(shè)置成100它都不動(dòng),為什么呢?因?yàn)榇藭r(shí)他和屏幕處在 平行狀態(tài),z軸方向上的分內(nèi)容為0,因此,參數(shù)設(shè)置多少都不變。那如果我們把粉色塊旋轉(zhuǎn)一下使得z軸上有分內(nèi)容,來(lái)對(duì)比一下效果:

.scaled {
  /* Includes a perspective to create a 3D space */
  transform: perspective(100px) scaleZ(1) rotateY(-20deg);
  background-color: pink;
}


如果此時(shí)將scale參數(shù)設(shè)置為2,結(jié)果如下:

可以看到z軸上的效果明顯增強(qiáng)了,或許你會(huì)覺(jué)得,這不是旋轉(zhuǎn)的角度增大了么,其實(shí)不然!不信來(lái)看看
rotateY(-40deg) 的效果

<div class="scaled">Scaled</div>
<div class="rotated">rotated</div>
.scaled {
  /* Includes a perspective to create a 3D space */
  transform: perspective(100px) scaleZ(2) rotateY(-20deg);
  background-color: pink;
}

.rotated {
  /* Includes a perspective to create a 3D space */
  transform: perspective(100px) scaleZ(1) rotateY(-40deg);
  background-color: pink;
}


? 大家應(yīng)該也能看出區(qū)別來(lái),rotate的旋轉(zhuǎn)會(huì)使圖像的寬度發(fā)生變化,如果旋轉(zhuǎn)90°,處在與屏幕垂直狀態(tài),看官就看不到這個(gè)圖形了,而 scaleZ() 只會(huì)修改圖形在z軸上的拉伸,并不會(huì)改變圖形的寬度。
?

# 旋轉(zhuǎn) - transfrom: rotate(angle)

? rotate2d旋轉(zhuǎn)系列,有: rotate(angle)

】與前兩個(gè)不同,rotateX, rotateYrotateZ都為rotate3d旋轉(zhuǎn)
? 參數(shù) angle 表示旋轉(zhuǎn)角度,單位為 deg ;當(dāng)角度為正數(shù)時(shí)表示順時(shí)針旋轉(zhuǎn),為負(fù)數(shù)時(shí)表示逆時(shí)針旋轉(zhuǎn),來(lái)看一個(gè)例子:

<div>Nomal</div>
<div class="rotated">Rotated</div>
<div class="rotated2">Rotated2</div>
div {
  display: inline-block;
  width: 80px;
  height: 50px;
}
.rotated {
  transform: rotate(30deg);
}
.rotated2 {
  transform: rotate(-30deg);
}
image.png
? rotate3d旋轉(zhuǎn)系列,有:rotateX(angle), rotateY(angle), rotateZ(angle), rotate3d(x, y, z, angle)

? 要解釋3d旋轉(zhuǎn),必須要先弄清楚旋轉(zhuǎn)軸。關(guān)于旋轉(zhuǎn)軸,如下:


? 其中,網(wǎng)布就是我們的屏幕,x軸沿屏幕平行的水平方向,y軸沿屏幕平行的垂直方向,z軸沿與屏幕垂直方向。
? rotateX(angle)表示沿著x軸旋轉(zhuǎn),經(jīng)過(guò)旋轉(zhuǎn)后,內(nèi)容以傾斜形式呈現(xiàn),所以,高度會(huì)減少;rotateY(angle) 沿著y軸旋轉(zhuǎn),所以寬度會(huì)減少,rotateZ(angle) 有些奇怪,與我們平時(shí)所想的不太一致,他是沿著屏幕做傾斜旋轉(zhuǎn)。

.rotateX {
  transform: rotateX(45deg);
}
.rotateY {
  transform: rotateY(45deg);
}
.rotateZ {
  transform: rotateZ(30deg);
}


?或許你不明白,為什么我旋轉(zhuǎn)了之后沒(méi)有出現(xiàn)矩形效果呢?更近的地方不應(yīng)該看起來(lái)更大嗎?非常好的問(wèn)題,說(shuō)明你思考了,這里我們漏了一個(gè)很重要的因素,設(shè)定3D環(huán)境 perspective;在沒(méi)有設(shè)定視距條件下,會(huì)被默認(rèn)為視距無(wú)窮遠(yuǎn),因此旋轉(zhuǎn)得到的微弱的梯形效果也就忽略了。 加上視距得到如下

.rotateX {
  transform: perspective(100px) rotateX(45deg);
}
.rotateY {
  transform: perspective(100px) rotateY(45deg);
}
.rotateZ {
  transform: perspective(100px) rotateZ(30deg);
}


? 這才是正確的效果。
? 再來(lái)學(xué)習(xí) rotate3d(x,y,z,angle);看起來(lái)很難,其實(shí)很簡(jiǎn)單。前三個(gè)參數(shù)取值為 -1,0,1 分別表示反向旋轉(zhuǎn),不旋轉(zhuǎn),正向旋轉(zhuǎn);第四個(gè)參數(shù)表示旋轉(zhuǎn)角度。

.rotate3d {
  background: lightgreen;
  transform: perspective(100px) rotate3d(1,0,-1,30deg);
}

?

# 傾斜 - transform: skew(x-angle, y-angle)

? skew傾斜系列

? skew傾斜允許使用一個(gè)值,當(dāng)使用一個(gè)值時(shí)表示 y-angle 為0;傾斜有一個(gè)難點(diǎn)就是它的直角坐標(biāo)系,關(guān)于官方的一大堆解釋我們不做深入研究,為方便理解,如下(圖侵刪)


? 也就是說(shuō),x軸的方向是豎直方向的,y軸的方向是水平方向的。以逆時(shí)針為正角度方向

.skewed {
  transform: skewX(45deg);
}
.skewed {
  transform: skewY(20deg);
}


特別注意】原點(diǎn)在圖形的中心位置,而不是在任何一個(gè)角上。直角坐標(biāo)系的第四象限(盒子所在位置)是正值所在區(qū)域。所以,x軸正方向是逆時(shí)針?lè)较?,y軸的正方向是順時(shí)針?lè)较?/strong>

.skewed {
  transform: skewX(30deg,10deg);
}

?

# 矩陣 - matrix

? 矩陣是什么?別的一看就懂,但這個(gè)是什么?看不懂???其實(shí),矩陣就是這東西:


矩陣與圖形變換關(guān)系

? 還是不懂?簡(jiǎn)單來(lái)說(shuō),矩陣就是使圖形發(fā)生變化(傾斜,縮放,旋轉(zhuǎn),平移)的原理所在。接下來(lái)的內(nèi)容是頁(yè)面狗逆襲的途徑之一,需要點(diǎn)數(shù)學(xué)基礎(chǔ):

? 在線性代數(shù)中,矩陣是這樣的(以單位矩陣為例)


其實(shí)該圖也是CSS中矩陣的初始值。但我們的矩陣一般都不會(huì)這么簡(jiǎn)單,都會(huì)有一些初始值,語(yǔ)法如下,其中 a b c e d f 都為數(shù)值,這么寫是為了方便區(qū)分

transform: matrix(a,b,c,d,e,f);

如果你非要用坐標(biāo)來(lái)理解,也可以看成是

transform: matrix(x1, x2, y1, y2, z1,z2)

不過(guò)我擔(dān)心你會(huì)越理解越混。寫成向量形式就是

當(dāng)我們要做變換時(shí),實(shí)質(zhì)上就是對(duì)初始值添加一些系數(shù),也就是:

所以我們能得到兩個(gè)式子:
x' = ax + cy +  e   // 即:x坐標(biāo)
y' = bx + dy + f    // 即:y坐標(biāo)

記住了,ax+cy+e為變換后的水平坐標(biāo),bx+dy+f表示變換后的垂直位置。

說(shuō)了這么一大堆,矩陣到底和圖形變換有什么關(guān)系?我怎么越看越迷糊了?
? 不急,既然要’逆襲‘,就不可能那么簡(jiǎn)單,為加深理解,看一個(gè)例子來(lái)直觀理解一下

transform: matrix(1,o,o,1,3o,3o);    /* a=1, b=0, c=0, d=1, e=30, f=30 */

假設(shè)矩陣偏移的中心點(diǎn)是 (0,0) , 即 x=0; y=0; 有如下式子

x' = ax + cy +  e  = 1*0 + 0*0 + 30 = 30
y' = bx + dy + f = 0*1 + 1*0 + 30 = 30

于是,我們得到偏移后的坐標(biāo)為 (30,30);這是什么變化?相信大家都猜到了,沒(méi)錯(cuò),這是平移變化,即

transform: translate(30px, 30px)

聰明的你或許已經(jīng)看破了,對(duì)于平移效果,其實(shí)矩陣公式是這樣的;

transform: matrix(跟我無(wú)關(guān), 我不知道, 一邊玩去, 愛(ài)咋咋地, x軸偏移量,y軸偏移量)

前面是個(gè)參數(shù)都是沒(méi)用的,因?yàn)橄禂?shù)(x,y) 為0.

? 平移容易理解,那么,其他效果呢? 我們來(lái)看看縮放:
? 或許你也猜到了,和縮放相關(guān)的也是兩個(gè)參數(shù),是的,完全正確,假設(shè)比例是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;
也就是
transform: matrix(sx,0,0,sy,0,0); 等同于 scale(sx, sy);

? 前兩個(gè)都還能接受,旋轉(zhuǎn)就選對(duì)復(fù)雜些,需要用到三角函數(shù),使用參數(shù)如下:

matrix(cosθ,sinθ,-sinθ,cosθ,0,0)

結(jié)合矩陣公式有

x' = x*cosθ-y*sinθ+0 = x*cosθ-y*sinθ
y' = x*sinθ+y*cosθ+0 = x*sinθ+y*cosθ

我們可能計(jì)算得到如下一個(gè)式子:

transform: matrix(0.866025,0.500000,-0.500000,0.866025,0,0);

好難好難,其實(shí)說(shuō)實(shí)在的,要是我肯定不這么寫,太麻煩了,用 rotate(20deg) 還是直接很多。

? 拉伸(skew) 也比較復(fù)雜,也是用到三角函數(shù),使用參數(shù)如下,

matrix(1,tan(θy),tan(θx),1,0,0)

套用矩陣公式計(jì)算結(jié)果為:

x' = x+y*tan(θx)+0 = x+y*tan(θx) 
y' = x*tan(θy)+y+0 = x*tan(θy)+y

對(duì)應(yīng)于skew(θx + "deg",θy+ "deg")這種寫法。
好麻煩好麻煩,我也不想用 matrix 來(lái)表示拉伸。

matrix 工具

估計(jì)你看完 martix 還是滿腦渾水,推薦一個(gè)測(cè)試工具矩陣變形,可以在里面自己多做些嘗試。

# 視距 - perspective

? 視距表示觀察者距離圖像的距離,是繪制3d效果必不可少的屬性之一??梢曰仡櫼幌麻_(kāi)篇第一張圖片,眼睛位置就是觀察者位置,d + z (z可以是負(fù)數(shù)) 就表示的是視距。

? 視距的表示有兩種方法,一種是:

transform: perspective(100px);

另一種是

perspective: 100px;

前者作為transform的值來(lái)使用,后者作為transform的前置屬性,不過(guò)需要兩種效果不太一致,前置屬性需要設(shè)置在父元素上生效。

# 后語(yǔ)

? 本文主要介紹 transform 的可選值以及它們的具體用法,知識(shí)點(diǎn)有些多需要大家慢慢消化,另外前置屬性還算相對(duì)容易一些,可以自行去了解一下用法。本文如果有不對(duì)或不好的地方,歡迎到評(píng)論區(qū)交流。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • CSS里transform變形這個(gè)屬性有點(diǎn)學(xué)習(xí)難度,尤其在CSS3里加上了3D效果之后,2維變3維學(xué)習(xí)成本更是成倍...
    BULL_DEBUG閱讀 983評(píng)論 0 1
  • CSS里transform變形這個(gè)屬性有點(diǎn)學(xué)習(xí)難度,尤其在CSS3里加上了3D效果之后,2維變3維學(xué)習(xí)成本更是成倍...
    張歆琳閱讀 28,416評(píng)論 5 81
  • 關(guān)于css3變形 CSS3變形是一些效果的集合,比如平移、旋轉(zhuǎn)、縮放和傾斜效果,每個(gè)效果都被稱作為變形函數(shù)(Tra...
    hopevow閱讀 6,569評(píng)論 2 13
  • Transform字面上就是變形,改變的意思。在CSS3中transform主要包括以下幾種:旋轉(zhuǎn)rotate、扭...
    hzrWeber閱讀 22,256評(píng)論 0 19
  • 看了很多視頻、文章,最后卻通通忘記了,別人的知識(shí)依舊是別人的,自己卻什么都沒(méi)獲得。此系列文章旨在加深自己的印象,因...
    DCbryant閱讀 1,972評(píng)論 0 4

友情鏈接更多精彩內(nèi)容