iOS開(kāi)發(fā)經(jīng)驗(yàn)(6)-Transform

目錄(transform)

  1. 基礎(chǔ)及矩陣概念
  2. 2D仿射
  3. 3D仿射
1. 基礎(chǔ)及矩陣概念
仿射變換.png
  • 在iOS的動(dòng)畫(huà)效果中,變換是很常見(jiàn)的,包括仿射變換和3D變換等。變換的終極原理就是矩陣的乘法運(yùn)算,3D變換涉及到三維透視投影的一些原理知識(shí)。
  • transform基本概念
    transform在矩陣變換的層面上改變視圖的顯示效果,完成旋轉(zhuǎn)、形變、平移等等操作。在它被修改的同時(shí),視圖的frame也會(huì)被真實(shí)改變。有兩個(gè)數(shù)據(jù)類(lèi)型用來(lái)表示transform,分別是CGAffineTransformCATransform3D。前者作用于UIView,后者為layer層次的變換類(lèi)型?;诤笳呖梢詫?shí)現(xiàn)更加強(qiáng)大的功能。
    UIView可以通過(guò)設(shè)置transform屬性做變換,但實(shí)際上它只是封裝了內(nèi)部圖層的變換。
    CALayer同樣也有一個(gè)transform屬性,但它的類(lèi)型是CATransform3D,而不是CGAffineTransform。CALayer對(duì)應(yīng)于UIViewtransform屬性叫做affineTransform,
  • 矩陣概念
    矩陣 × 坐標(biāo):當(dāng)你用矩陣乘以一個(gè)坐標(biāo)時(shí),它們的乘積就是一個(gè)變換后的新坐標(biāo)。
    齊次坐標(biāo):為了把二維圖形的變化統(tǒng)一在一個(gè)坐標(biāo)系里,引入了齊次坐標(biāo)的概念,即把一個(gè)圖形用一個(gè)三維矩陣表示,其中第三列總是(0,0,1)(為了能讓矩陣做乘法),用來(lái)作為坐標(biāo)系的標(biāo)準(zhǔn)。所以所有的變化都由前兩列完成
    為了能讓矩陣做乘法:左邊矩陣的列數(shù)一定要和右邊矩陣的行數(shù)個(gè)數(shù)相同,所以要給矩陣填充一些標(biāo)志值,使得既可以讓矩陣做乘法,又不改變運(yùn)算結(jié)果,并且沒(méi)必要存儲(chǔ)這些添加的值,因?yàn)樗鼈兊闹挡粫?huì)發(fā)生變化,但是要用來(lái)做運(yùn)算。因此,通常會(huì)用3×3(而不是2×3)的矩陣來(lái)做二維變換.
    當(dāng)對(duì)圖層應(yīng)用變換矩陣,圖層矩形內(nèi)的每一個(gè)點(diǎn)都被相應(yīng)地做變換,從而形成一個(gè)新的四邊形的形狀。CGAffineTransform中的“仿射”的意思是無(wú)論變換矩陣用什么值,圖層中平行的兩條線在變換之后任然保持平行,CGAffineTransform可以做出任意符合上述標(biāo)注的變換
    單位矩陣
CGAffineTransformIdentity
  • 仿射變換的原理和計(jì)算
    仿射變化原理是數(shù)學(xué)中的矩陣原理(線性代數(shù)-矩陣分析),要弄明白仿射矩陣對(duì)作用點(diǎn)的影響,還得先看看矩陣的乘法怎么計(jì)算。

    基礎(chǔ)-矩陣的乘法
    計(jì)算規(guī)則:

    • 不符合交換律(A和B是矩陣,AB不一定等于BA)
    • 當(dāng)矩陣A的列數(shù)等于矩陣B的行數(shù)是,才可以計(jì)算
    • 計(jì)算的結(jié)果矩陣C的行數(shù)等于A的行數(shù),列數(shù)等于B的列數(shù)(如A是m×n矩陣和B是n×p矩陣,它們的乘積C是一個(gè)m×p矩陣 )
    • 結(jié)果矩陣C的第 i 行第 j 列的元素Cij 等于矩陣A的第 i 行的元素與矩陣B的第 j 列對(duì)應(yīng)元素乘積之和
矩陣A = 
[1  1]
[2  0]
矩陣B = 
[0  2  3]
[1  1  2]
計(jì)算過(guò)程:
矩陣C = A * B =    
[(1 * 0 + 1 * 1) (1 * 2 + 1 * 1) (1 * 3 + 1 * 2)] 
[(2 * 0 + 0 * 1) (2 * 2 + 0 * 1) (2 * 3 + 0 * 2)]   
矩陣C =
[1 3 5]
[0 4 6]
  • 仿射變換的矩陣計(jì)算
    仿射計(jì)算中,(以二維坐標(biāo)為例,坐標(biāo)點(diǎn)為x,y)我們?cè)O(shè)我們的坐標(biāo)點(diǎn)矩陣為
坐標(biāo)點(diǎn)矩陣
A = [x y 1]

仿射變換基礎(chǔ)矩陣為:

B = 
[a  b  0]
[c  d  0]
[tx ty 1]

根據(jù)矩陣計(jì)算規(guī)則我們知道A x B的結(jié)果是一個(gè)1行3列的矩陣,設(shè)A x B得到的新矩陣C ,那么C的矩陣應(yīng)該為

C = [(a*x+c*y+tx) (b*x+d*y+ty) 1]
設(shè)C為 = [x' y' 1] , 那么可以得到
x' = a*x + c*y + tx
y' = b*x + d*y + ty
2. 2D仿射
  • 仿射是什么
    仿射變換可以理解為
    • 對(duì)坐標(biāo)進(jìn)行放縮,旋轉(zhuǎn),平移后取得新坐標(biāo)的值。
    • 經(jīng)過(guò)對(duì)坐標(biāo)軸的放縮,旋轉(zhuǎn),平移后原坐標(biāo)在在新坐標(biāo)領(lǐng)域中的值。
    • transform是一個(gè)矩陣,變換后的點(diǎn)坐標(biāo)等于之前的點(diǎn)坐標(biāo)乘以矩陣

當(dāng)操縱一個(gè)變換的時(shí)候,初始生成一個(gè)什么都不做的變換很重要--也就是創(chuàng)建一個(gè)CGAffineTransform類(lèi)型的空值,矩陣論中稱作單位矩陣,Core Graphics同樣也提供了一個(gè)方便的常量:CGAffineTransformIdentity
iOS封裝了幾個(gè)好用的CGAffineTrans的API去實(shí)現(xiàn)仿射變換的效果
注意:帶Make的,起點(diǎn)固定,每次控制的事件只針對(duì)起點(diǎn)。不帶Make的:為一個(gè)變換再加上平移,針對(duì)上一個(gè)位置,不針對(duì)起點(diǎn)。

//位移仿射
CGAffineTransformMakeTranslation
CGAffineTransformTranslate
//旋轉(zhuǎn)仿射
CGAffineTransformMakeRotation
CGAffineTransformRotate
//縮放仿射
CGAffineTransformMakeScale
CGAffineTransformScale
//疊加仿射效果
CGAffineTransformConcat
//仿射矩陣方法,可以直接做效果疊加
CGAffineTransformMake (sx,shx,shy,sy,tx,ty)

帶make的方法是直接返回一個(gè)仿射變換效果,不帶make方法是用來(lái)給已有的仿射效果疊加效果
類(lèi)似于CGAffineTransformConcat方法的作用
CATransform3D也對(duì)應(yīng)一組相似的api,這個(gè)后面在研究到它的時(shí)候仔細(xì)說(shuō)說(shuō).

在大多數(shù)情況下用這幾個(gè)封裝好的仿射方法基本就能實(shí)現(xiàn)大多數(shù)的需求。但是既然是研究仿射,可以看CGAffineTransform最基礎(chǔ)的那個(gè)仿射方法的使用,能理解這個(gè)方法的使用,基本上就知道仿射是個(gè)什么意思了。

CGAffineTransformMake(CGFloat a,CGFloat b,CGFloat c,CGFloat d,CGFloat tx,CGFloat ty)

這個(gè)方法的6個(gè)參數(shù)可以拼出一個(gè)矩陣

//仿射矩陣
[a  b  0]
[c  d  0]
[tx ty 1]

仿射變化的定義有點(diǎn)復(fù)雜,我自己理解就是: 點(diǎn)p(以二維坐標(biāo)為例)通過(guò)仿射矩陣C 后變成新的點(diǎn)p' 。
以上面的縮放仿射變化CGAffineTransformScale為例。就是view中每一個(gè)點(diǎn)p通過(guò)矩陣C后,view中的每一個(gè)新的點(diǎn)p'組成的新的圖形,相比之前的view有了縮放的效果。

這步很關(guān)鍵。根據(jù)這個(gè)公式,那么仿射矩陣就可以分成5種分別對(duì)應(yīng):平移(Translation),縮放(Scale),翻轉(zhuǎn)(Flip),旋轉(zhuǎn)(Rotation),剪切(Shear)

平移演化

設(shè)a,d=1 c,b = 0 那么
x' = a*x + c*y + tx
y' = b*x + d*y + ty
就變成了
x' = x + tx
y' = y + ty

這個(gè)不就是新的點(diǎn)P'(x' y') 是根據(jù)原來(lái)的P在x和y分別添加了一個(gè)常量就可以得到了嘛? 所以這個(gè)就是仿射中的平移效果了。把a(bǔ),b,c,d帶入仿射的基礎(chǔ)矩陣,就得了仿射的位移矩陣

//仿射基礎(chǔ)矩陣
[a  b  0]
[c  d  0]
[tx ty 1]
//仿射位移矩陣
[1  0  0]
[0  1  0]
[tx ty 1]

再來(lái)看看代碼

向右移動(dòng)300的仿射效果
CGAffineTransform translate = CGAffineTransformMakeTranslation(300, 0)
使用仿射基礎(chǔ)方法 
CGAffineTransform translate = CGAffineTransformMake(1,0,0,1,300,0)

縮放演化

x' = a*x + c*y + tx
y' = b*x + d*y + ty
設(shè) c,b,tx,ty = 0 ,得到
x' = a*x
y' = d*y

新坐標(biāo)(x',y')和原坐標(biāo)是倍數(shù)關(guān)系,這個(gè)就可以用來(lái)做縮放效果了。所以得到縮放矩陣

//仿射縮放矩陣
[a  0  0]
[0  d  0]
[0  0  1]
//也可以寫(xiě)成
[sx  0  0]
[0  sy  0]
[0   0  1]
代碼
//x和y都放大1倍
CGAffineTransform scaleAffine = CGAffineTransformMakeScale(2, 2)
//使用仿射基礎(chǔ)方法
CGAffineTransform scaleAffine = CGAffineTransformMake(2,0,0,2,0,0)

剪切演化

x' = a*x + c*y + tx
y' = b*x + d*y + ty
設(shè) a,d = 1 tx,ty = 0 ,得到
x' = x + cy
y' = y + bx

x和y的變化總是相互關(guān)聯(lián),這個(gè)就是剪切(Shear)

//仿射剪切矩陣
[1  b  0]
[c  1  0]
[0  0  1]
//也可以寫(xiě)成
[1  shx  0]
[shy  1  0]
[0    0  1]
代碼
//使用仿射基礎(chǔ)方法CGAffineTransformMake,設(shè)置x和y都為0.5的斜切
CGAffineTransform shearAffine = CGAffineTransformMake(1,0.5,0.5,1,0,0)

剪切效果只能用CGAffineTransformMake實(shí)現(xiàn),但是通過(guò)CATransform3DMakeRotation可以有類(lèi)似的效果
旋轉(zhuǎn)演化

//仿射旋轉(zhuǎn)矩陣
[cosa   sina  0]
[-sina  cosa  0]
[0      0     1]
代碼
CGAffineTransform rotation = CGAffineTransformMake(CGFloat( cos(M_PI_4) ), CGFloat( sin(M_PI_4) ), -CGFloat( sin(M_PI_4) ), CGFloat( cos(M_PI_4) ), 0, 0)

翻轉(zhuǎn)演化
我不知道使用CGAffineTransformMake()如何設(shè)置矩陣可以實(shí)現(xiàn)翻轉(zhuǎn)效果。我閱讀的所有Flip效果都是使用CATransform3D實(shí)現(xiàn)的,代碼如下

//Flip仿射,要是有3D去實(shí)現(xiàn)
CATransform3D flip = CATransform3DMakeRotation(angle, x, y, z)
//示例
CATransform3D flipX = CATransform3DMakeRotation(CGFloat(M_PI), 1, 0, 0)
CATransform3D flipY = CATransform3DMakeRotation(CGFloat(M_PI), 0, 1, 0)
CATransform3D flipZ = CATransform3DMakeRotation(CGFloat(M_PI), 0, 0, 1)

總結(jié)一下CATransform3DMakeRotation方法的6個(gè)參數(shù)

在不考慮旋轉(zhuǎn)時(shí),CATransform3DMakeRotation6個(gè)參數(shù)可以寫(xiě)成
//sx,sy:縮放因子
//shx,shy:斜切因子
//tx,ty:移動(dòng)因子
CGAffineTransformMake (sx,shx,shy,sy,tx,ty)

這個(gè)是一個(gè)初始化矩陣,帶入矩陣算法計(jì)算后的結(jié)構(gòu)會(huì)得到
x'=x , y'=y
它的作用是清除之前對(duì)矩陣設(shè)置的仿射效果,或者用來(lái)初始化一個(gè)原始無(wú)效果的仿射矩陣

矩陣初始值。[ 1 0 0 1 0 0 ]
[ 1 0 0 ]
[ 0 1 0 ]
[ 0 0 1 ]

方法:

 //用來(lái)連接兩個(gè)變換效果并返回。返回的t = t1 * t2
CGAffineTransformConcat(CGAffineTransform t1, CGAffineTransform t2)
//矩陣初始值。[ 1 0 0 1 0 0 ]
CGAffineTransformIdentity
//檢查是否有做過(guò)仿射效果
CGAffineTransformIsIdentity(transform)
//檢查2個(gè)仿射效果是否相同
CGAffineTransformEqualToTransform(transform1,transform2)
//仿射效果反轉(zhuǎn)(反效果,比如原來(lái)擴(kuò)大,就變成縮小)
CGAffineTransformInvert(transform)
  • 應(yīng)用
    放射矩陣一個(gè)常用的情形就是根據(jù)用戶的手勢(shì)來(lái)相應(yīng)的改變視圖的變換
    UIPanGestureRecognizer 對(duì)應(yīng)位移
    UIPinchGestureRecognizer 對(duì)應(yīng)縮放
    UIRotationGestureRecognizer 對(duì)應(yīng)旋轉(zhuǎn)
    通常如果需要看到實(shí)時(shí)的手指移動(dòng)視圖就相應(yīng)的變換的技巧就是,每次接收到對(duì)應(yīng)的gesture時(shí)間就相應(yīng)的改變view的transform,然后吧這個(gè)gesture對(duì)應(yīng)的translation、scale、rotation置為初始值。
3. 3D仿射
  • 三維坐標(biāo)系:視角垂直與屏幕而言,x軸向右,y軸向下,z軸垂直屏幕向外。和UIView嚴(yán)格的二維坐標(biāo)系不同,CALayer存在于一個(gè)三維空間當(dāng)中。CALayer還有另外兩個(gè)屬性,zPositionanchorPoint
    最實(shí)用的功能就是改變圖層的顯示順序。
self.greenView.layer.zPosition=1.0f;
  • 錨點(diǎn) anchorPoint
    圖層的錨點(diǎn)anchorPoint:是一個(gè)CGPoint值,x,y取值范圍(0~1),默認(rèn)為(0.5,0.5) 對(duì)于圖層本身而言,顧名思義,錨點(diǎn)就用來(lái)定位圖層的點(diǎn)。錨點(diǎn)有兩個(gè)職能:
    (1)與position一同確定圖層相對(duì)于父圖層的位置;
    (2)通過(guò)設(shè)置該屬性來(lái)實(shí)現(xiàn)視圖圍繞不同位置旋轉(zhuǎn)。記得在視圖添加到父視圖之后在進(jìn)行設(shè)置,因?yàn)閒rame也是相對(duì)于錨點(diǎn)的。
作為圖層旋轉(zhuǎn)、平移、縮放的中心
self.menuViewController.view.layer.anchorPoint = CGPointMake(1.0,0);

當(dāng)圖層發(fā)生變換時(shí),這個(gè)點(diǎn)永遠(yuǎn)位于圖層變換之前anchorPoint的位置。當(dāng)改變一個(gè)圖層的position,你也改變了它的錨點(diǎn),做3D變換的時(shí)候要時(shí)刻記住這一點(diǎn),當(dāng)你視圖通過(guò)調(diào)整m34來(lái)讓它更加有3D效果,應(yīng)該首先把它放置于屏幕中央,然后通過(guò)平移來(lái)把它移動(dòng)到指定位置(而不是直接改變它的position),這樣所有的3D圖層都共享一個(gè)錨點(diǎn)。

  • 關(guān)于錨點(diǎn)(anchorPoint)與position
  • position是決定了layer顯示在父控件的哪個(gè)位置,默認(rèn)position是該layer的中心點(diǎn).
  • anchorPoint決定了layer自身顯示在position的哪個(gè)位置.
  • position與錨點(diǎn)的默認(rèn)點(diǎn)為中心點(diǎn)
  • position總是與錨點(diǎn)顯示在同一位置
  • layer是否發(fā)生偏移有錨點(diǎn)決定
  • 3D仿射矩陣
    3D仿射矩陣類(lèi)似于2D仿射,3D仿射也有一個(gè)基礎(chǔ)矩陣,并且比2D的多一個(gè)維度
CGAffineTransform transform = CGAffineTransformIdentity;
結(jié)果:(CGAffineTransform) transform = (a = 1, b = 0, c = 0, d = 1, tx = 0, ty = 0)
[m11  m12  m13  m14]
[m21  m22  m23  m24]
[m31  m32  m33  m34]
[m41  m42  m43  m44]

矩陣的計(jì)算過(guò)程和2D類(lèi)似,最后也能得到矩陣中每個(gè)位置的值對(duì)3D仿射效果的作用。我直接把結(jié)果貼出來(lái)。

平移因子: m41(x位置) m42(y位置) m43(z位置) 
縮放因子: m11(x位置) m22(y位置)
切變因子: m21(x位置) m12(y位置)
旋轉(zhuǎn)因子: m13(x位置) m31(y位置)
透視因子: m34(有旋轉(zhuǎn)才能看出效果)

m34的默認(rèn)值是0,我們可以通過(guò)設(shè)置m34為(-1.0 / d)來(lái)應(yīng)用透視效果,d代表了視角相機(jī)和屏幕之間的距離,以像素為單位,那應(yīng)該如何計(jì)算這個(gè)距離呢?大概估算一個(gè)就行了。
因?yàn)橐暯窍鄼C(jī)實(shí)際上并不存在,所以可以根據(jù)屏幕上的顯示效果自由決定它放置的位置。通常500-1000就已經(jīng)很好了,但對(duì)于特定的圖層有時(shí)候更小后者更大的值會(huì)看起來(lái)更舒服,減少距離的值會(huì)增強(qiáng)透視效果,所以一個(gè)非常微小的值會(huì)讓它看起來(lái)更加失真,然而一個(gè)非常大的值會(huì)讓它基本失去透視效果
3D仿射常用的方法

//位移3D仿射
CATransform3DMakeTranslation
CATransform3DTranslation
//旋轉(zhuǎn)3D仿射:x-y-z軸的有個(gè)確定的范圍(介于-1 和+1之間)
CATransform3DMakeRotation
CATransform3DRotation
angle 是所需要變化的角度
x y z 設(shè)置為零表示不圍繞該軸做旋轉(zhuǎn),如果設(shè)置為1,則繞該軸做旋轉(zhuǎn)。
//縮放3D仿射
CATransform3DMakeScale
CATransform3DScale
//疊加3D仿射效果
CATransform3DConcat
//仿射基礎(chǔ)3D方法,可以直接做效果疊加
CGAffineTransformMake (sx,shx,shy,sy,tx,ty)
矩陣初始值:[ 1 0 0 0 1 0 0 0 1 0 0 0]

這個(gè)是一個(gè)初始化矩陣,帶入矩陣算法計(jì)算后的結(jié)構(gòu)會(huì)得到

x'=x , y'=y , z'=z

它的作用是清除之前對(duì)矩陣設(shè)置的仿射效果,或者用來(lái)初始化一個(gè)原始無(wú)效果的仿射矩陣

矩陣初始值:
[ 1 0 0 0 ]
[ 0 1 0 0 ]
[ 0 0 1 0 ]
[ 0 0 0 1 ]
//矩陣初始值。[ 1 0 0 0 1 0 0 0 1 0 0 0]
CATransform3DIdentity
//檢查是否有做過(guò)仿射3D效果
CATransform3DIsIdentity(transform)
//檢查是否是一個(gè)仿射3D效果
CATransform3DIsAffine(transform)
//檢查2個(gè)3D仿射效果是否相同
CATransform3DEqualToTransform(transform1,transform2)
//3D仿射效果反轉(zhuǎn)(反效果,比如原來(lái)擴(kuò)大,就變成縮?。?CATransform3DInvert(transform)
//2D仿射轉(zhuǎn)換3D仿射
CATransform3DGetAffineTransform(transform)
CATransform3DMakeAffineTransform(transform)

CATransform3D與CGAffineTransform的轉(zhuǎn)換

//將一個(gè)CGAffinrTransform轉(zhuǎn)化為CATransform3DCATransform3D 
CATransform3DMakeAffineTransform (CGAffineTransform m);
//判斷一個(gè)CATransform3D是否可以轉(zhuǎn)換為CAAffineTransformbool
CATransform3DIsAffine (CATransform3D t);
//將CATransform3D轉(zhuǎn)換為CGAffineTransformCGAffineTransform
CATransform3DGetAffineTransform (CATransform3D t);

當(dāng)我們改變過(guò)一個(gè)view.transform屬性或者view.layer.transform的時(shí)候需要恢復(fù)默認(rèn)狀態(tài)的話,記得先把他 們重置為

view.transform = CGAffineTransformIdentity;
view.layer.transform = CATransform3DIdentity;

CALayertransform屬性是是個(gè)CATransform3D類(lèi)型的數(shù)據(jù),默認(rèn)值為CATransform3DIdentity。需要注意的是,CALayer是有隱式動(dòng)畫(huà)的,如果你想關(guān)掉隱式動(dòng)畫(huà),用

[CATransaction setDisableActions:YES];

另外,要特地說(shuō)明一下矩陣中的一個(gè)參數(shù)m34,m34影響透視效果.當(dāng)然,z方向上得有變化才會(huì)有透視效果,數(shù)值越大,透視效果越明顯.正值/負(fù)值都有意義,導(dǎo)致透視方向的不同。d越大,效果越不明顯,d越小,效果越明顯甚至導(dǎo)致失真。d的一個(gè)推薦的值是500-1000之間。

  • 透視效果
#define RADIANS_TO_DEGREES(x) ((x)/M_PI*180.0)
CATransform3D transform = CATransform3DIdentity;
// 透視效果
transform.m34 = 0.0005; 
transform = CATransform3DRotate(transform,(M_PI/180*40), 0, 1, 0);
[layer setTransform:transform];
注意我們使用的旋轉(zhuǎn)常量是`M_PI_4`,而不是你想象的`45`,因?yàn)閕OS的變換函數(shù)使用弧度而不是角度作為單位。
弧度用數(shù)學(xué)常量`pi`的倍數(shù)表示,一個(gè)`pi`代表`180`度,所以四分之一的`pi`就是`45`度。

第二行一定要寫(xiě)在第三行的前面;m34:透視效果m34= -1/M,M越小,透視效果越明顯,必須在有旋轉(zhuǎn)效果的前提下,才會(huì)看到透視效果。

  • 合并兩個(gè)CATransform3D(CATransform3DConcat)
CATransform3D CATransform3DConcat ( CATransform3D a, CATransform3D b );
  • CATransform3DInvert效果反轉(zhuǎn)(反效果,比如原來(lái)擴(kuò)大,就變成縮?。?/li>
CATransform3D CATransform3DInvert ( CATransform3D t );
  • CATransform3D與CGAffineTransform的轉(zhuǎn)換
//將一個(gè)CGAffinrTransform轉(zhuǎn)化為CATransform3DCATransform3D 
CATransform3DMakeAffineTransform (CGAffineTransform m);
//判斷一個(gè)CATransform3D是否可以轉(zhuǎn)換為CAAffineTransformbool 
CATransform3DIsAffine (CATransform3D t);
//將CATransform3D轉(zhuǎn)換為CGAffineTransformCGAffineTransform 
CATransform3DGetAffineTransform (CATransform3D t);
  • 減輕鋸齒-shouldRasterize
    屬性的默認(rèn)值是NO,可將其設(shè)置為YES來(lái)減輕鋸齒的效果。記得動(dòng)畫(huà)結(jié)束時(shí)將其設(shè)置為 NO
self.menuViewController.view.layer.shouldRasterize = NO;
  • content
    設(shè)置CALayercontents屬性為一個(gè)image來(lái)設(shè)置圖片,設(shè)置contentGravity來(lái)指定圖層內(nèi)容的拉伸方式。
    iOS CATransform3D ,旋轉(zhuǎn)之后出現(xiàn)的鋸齒處理方法
layer.shouldRasterize = YES;
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,797評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,179評(píng)論 3 414
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 175,628評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 62,642評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,444評(píng)論 6 405
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 54,948評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,040評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 42,185評(píng)論 0 287
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,717評(píng)論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,602評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,794評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,316評(píng)論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,045評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 34,418評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 35,671評(píng)論 1 281
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,414評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,750評(píng)論 2 370

推薦閱讀更多精彩內(nèi)容