《iOS核心動(dòng)畫高級(jí)技巧》筆記(二) - 圖層幾何學(xué)/視覺效果

圖層幾何學(xué)

  • 內(nèi)部是如何根據(jù)父圖層和兄弟圖層來控制位置和尺寸的,如何管理圖層的幾何結(jié)構(gòu),如何被自動(dòng)調(diào)整和自動(dòng)布局影響的。

布局

  • <mark>UIView有三個(gè)比較重要的布局屬性:frame,bounds 和 centerCALayer對(duì)應(yīng)地叫做frame,bounds 和 position。</mark>
  • frame代表了圖層的外部坐標(biāo)
  • bounds是內(nèi)部坐標(biāo)
  • centerposition都代表了相對(duì)于父圖層anchorPoint所在的位置。
  • 當(dāng)操縱視圖的frame,實(shí)際上是在改變位于視圖下方CALayerframe,不能夠獨(dú)立于圖層之外改變視圖的frame。
  • frame并不是一個(gè)非常清晰的屬性,它其實(shí)是一個(gè)虛擬屬性,是根據(jù)bounds,position和transform計(jì)算而來,所以當(dāng)其中任何一個(gè)值發(fā)生改變,frame都會(huì)變化。相反,改變frame的值同樣會(huì)影響到他們當(dāng)中的值
  • 如圖:當(dāng)對(duì)圖層做變換的時(shí)候,比如旋轉(zhuǎn)或者縮放,frame實(shí)際上代表了覆蓋在圖層旋轉(zhuǎn)之后的整個(gè)軸對(duì)齊的矩形區(qū)域,也就是說frame的寬高可能和bounds的寬高不再一致
3.2.jpeg

錨點(diǎn)

  • anchorPoint用單位坐標(biāo)來描述,默認(rèn)坐標(biāo)是{0.5, 0.5}
  • 個(gè)人理解:如下圖,中心點(diǎn)左右兩邊邊距皆為視圖寬度的一半,高度同理。改變視圖中心點(diǎn)的位置至左上角后,同樣有此規(guī)則,所以看到的視圖向右下角移動(dòng)了。
3.3.jpeg

坐標(biāo)系

  • 一個(gè)圖層的position依賴于它父圖層的bounds

  • CALayer提供了一些方法(把定義在一個(gè)圖層坐標(biāo)系下的點(diǎn)或者矩形轉(zhuǎn)換成另一個(gè)圖層坐標(biāo)系下的點(diǎn)或者矩形):

  • - (CGPoint)convertPoint:(CGPoint)point fromLayer:(CALayer *)layer;

  • - (CGPoint)convertPoint:(CGPoint)point toLayer:(CALayer *)layer;

  • - (CGRect)convertRect:(CGRect)rect fromLayer:(CALayer *)layer;

  • - (CGRect)convertRect:(CGRect)rect toLayer:(CALayer *)layer;

  • 翻轉(zhuǎn)的幾何結(jié)構(gòu):

  • iOS:圖層的position位于父圖層的左上角

  • Mac OS:位于左下角。

  • geometryFlipped:決定了一個(gè)圖層的坐標(biāo)是否相對(duì)于父圖層垂直翻轉(zhuǎn),是一個(gè)BOOL類型。(它的所有子圖層也同理,除非把它們的geometryFlipped屬性也設(shè)為YES)。

  • 個(gè)人理解:設(shè)置為YES,假設(shè)原坐標(biāo)系的起始點(diǎn)在左上角,現(xiàn)改成左下角,坐標(biāo)系隨之改變。

  • Z坐標(biāo)軸

  • CALayer存在于一個(gè)三維空間當(dāng)中,還有另外兩個(gè)屬性:

  • zPosition:最實(shí)用的功能就是改變圖層的顯示順序(圖層是根據(jù)它們子圖層的sublayers出現(xiàn)的順序來類繪制的),不能改變事件傳遞的順序。

  • anchorPointZ:改變錨點(diǎn)在Z軸的位置。

點(diǎn)擊測(cè)試

  • CALayer不直接處理觸摸,手勢(shì)事件,但有方法幫你處理事件。

  • -containsPoint::接受一個(gè)在本圖層坐標(biāo)系下的點(diǎn),如果這個(gè)點(diǎn)在圖層frame范圍內(nèi)就返回YES

  • [self.layerView.layer containsPoint:point]

  • -hitTest::接受一個(gè)在本圖層坐標(biāo)系下的點(diǎn),如果這個(gè)點(diǎn)在圖層frame范圍內(nèi)就返回圖層本身,在之外則返回nil。測(cè)算的順序嚴(yán)格依賴于圖層樹當(dāng)中的圖層順序。

  • [self.layerView.layer hitTest:point]

  • 如果改變了圖層的 Z 軸順序,將不能檢測(cè)到最前方的視圖點(diǎn)擊事件,因?yàn)楸涣硪粋€(gè)視圖遮蓋住了,雖然zPosition值較小,但是在圖層樹中的順序靠前。

自動(dòng)布局

  • CALayer的布局
  • 通過CALayerDelegatelayoutDublayersOfLayer:函數(shù)。當(dāng)圖層的bounds發(fā)生改變或者圖層的setNeedsLayout方法被調(diào)用的時(shí)候,該方法就會(huì)被執(zhí)行。
  • 不能像UIView一樣做到屏幕自適應(yīng),也是為什么使用視圖而不是圖層構(gòu)建程序的原因之一。

視覺效果

圓角

  • conrnerRadius:圓角的曲率,只影響背景顏色而不影響背景圖片或是子圖層。可以通過把masksToBounds設(shè)置成YES,圖層里面的所有東西都會(huì)被截取。
  • 創(chuàng)建一個(gè)有圓角和直角的圖形可以通過圖層蒙板或者CAShapeLayer。

圖層邊框

  • borderWidth
  • borderColor:CGColorRef類型
  • 邊框是跟隨圖層的邊界變化的,而不是圖層里面的內(nèi)容

陰影

  • shadowOpacity:0(不可見) ~ 1(完全不透明)
  • shadowColor: 陰影的顏色
  • shadowOffset: 陰影的方向和距離,默認(rèn) {0, -3},寬度決定橫向位移,高度決定縱向位移。(前身是 Mac OS,兩者 Y 軸顛倒,Mac OS 陰影朝下,iOS就朝上了)
  • shadowRadius: 陰影模糊度

陰影裁剪

  • 圖層的陰影繼承自內(nèi)容的外形,而不是根據(jù)邊界和角半徑來確定。
  • masksToBounds把陰影裁剪的解決辦法:
  • 兩個(gè)圖層:一個(gè)只畫陰影的空的外圖層,一個(gè)用masksToBounds裁剪內(nèi)容的內(nèi)圖層。

shadowPath屬性

  • 計(jì)算陰影是個(gè)消耗性能的操作,通過該屬性來告訴系統(tǒng)陰影的形狀,提高性能。
  • CGPathRef類型,一個(gè)指向CGPath的指針,CGPath是一個(gè)Core Graphics對(duì)象,用來指定任意的一個(gè)矢量圖形。
  • 該屬性用來指定任意陰影形狀

圖層蒙版

  • mask屬性:圖層實(shí)心部分會(huì)被保留下來,其他地方會(huì)被拋棄。
Snip20170525_2.png
@interface ViewCOntroller
@property (nonatomic, weak) IBOutlet UIImageView *imageView
@end

@implementation ViewController
- (void)viewDidLoad{
      [super viewDidLoad];
      CALayer *maskLayer = [CALayer layer];
      maskLayer.frame = self.layerView.bounds;
      UIImage *maskImage = [UIImage imageNamed:@"Cone.png"];
      maskLayer.contents = (__bridge id)maskImage.CGImage;

      self.imageView.layer.mask = maskLayer;
}
@end

拉伸過濾

  • 以正確的比例和正確的1:1像素顯示在屏幕上
    • 能夠顯示最好的畫質(zhì),像素既沒有被壓縮也沒有被拉伸。
    • 能更好的使用內(nèi)存,因?yàn)檫@就是所有你要存儲(chǔ)的東西。
    • 最好的性能表現(xiàn),CPU不需要為此額外的計(jì)算。
  • minificationFilter:縮小圖片,magnificationFilter:放大圖片
  • kCAFilterLinear:默認(rèn)值,采用雙線性濾波算法,通過對(duì)多個(gè)像素取樣最終生成新的值,得到一個(gè)平滑的表現(xiàn)不錯(cuò)的拉伸。但是當(dāng)放大倍數(shù)比較大的時(shí)候圖片就模糊不清。
  • kCAFilterTrilinear:和kCAFilterLinear非常相似,采用三線性濾波算法存儲(chǔ)了多個(gè)大小情況下的圖片(也叫多重貼圖),并三維取樣,同時(shí)結(jié)合大圖和小圖的存儲(chǔ)進(jìn)而?得到最后的結(jié)果。<mark>好處:在于算法能夠從一系列已經(jīng)接近于最終大小的圖片中得到想要的結(jié)果,也就是說不要對(duì)很多像素同步取樣。這不僅提高了性能,也避免了小概率因舍入錯(cuò)誤引起的取樣失靈的問題</mark>
  • kCAFilterNearest:采用最近過濾算法,取樣最近的單像素點(diǎn)而不管其他的顏色。速度快不會(huì)產(chǎn)生模糊,但會(huì)降低質(zhì)量并像素化圖像,馬賽克化。適用于比較小的圖或者是差異特別明顯,極少斜線的大圖。

組透明

  • 如果你給一個(gè)圖層設(shè)置了opacity屬性,那它的子圖層都會(huì)受此影響。
  • 當(dāng)你顯示一個(gè)50%透明度的圖層時(shí),圖層的每個(gè)像素都會(huì)一半顯示自己的顏色,另一半顯示圖層下面的顏色。這是正常的透明度的表現(xiàn)。
  • 但是如果圖層包含一個(gè)同樣顯示50%透明的子圖層時(shí),你所看到的視圖,50%來自子視圖,25%來了圖層本身的顏色,另外的25%則來自背景色。
  • 個(gè)人理解:當(dāng)只有一個(gè)圖層時(shí),50%是自己的顏色,50%是背景的;當(dāng)一個(gè)圖層有一個(gè)子圖層時(shí),50%自己,另外50%的一半給父圖層,一半給背景顏色。
Snip20170526_1.png
  • 整體透明解決方案:
  • 設(shè)置Info.plist文件中的UIViewGroupOpacityYES來達(dá)到這個(gè)效果,但會(huì)影響到這個(gè)應(yīng)用其他部分。
  • CALayershouldRasterize屬性為YES,在應(yīng)用透明度之前,圖層及其子圖層都會(huì)被整合成一個(gè)整體的圖片,這樣就沒有透明度混合的問題了

當(dāng)shouldRasterizeUIViewGroupOpacity一起的時(shí)候,性能問題就出現(xiàn)了)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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