玩轉iOS開發:4.《Core Animation》CALayer的視覺效果

文章分享至個人我的博客: https://cainluo.github.io/14775511877452.htmlhtml


做者感言

前一章咱們對CALayer瞭解的更加深刻了一些《Core Animation》CALayer的幾何圖層今天咱們就來說講CALayer Visual Effects, 也就是CALayer的視覺效果.git

** 最後:** ** 若是你有更好的建議或者對這篇文章有不滿的地方, 請聯繫我, 我會參考大家的意見再進行修改, 聯繫我時, 請備註**`Core Animation`**若是以爲好的話, 但願你們也能夠打賞一下~嘻嘻~祝你們學習愉快~謝謝~**

簡介

CALayer Visual Effects講得是CALayer一些咱們可以看得見的東西, 這些知識點在咱們平常開發中也會有用到的, 好比Rounded Corners, Layer Borders, Drop Shadows, Layer Masking, Scaling Filters, Group Opacity等等, 待咱們一一去講解.github


Rounded Corners

Rounded Corners這個東西咱們用的其實也是挺多的, 咱們都知道, 在iOS 7以前, 基本上全部的Button都是橢圓形的, 而這些Button之因此都是橢圓形, 大多數都是由於Rounded Corners這個東西的緣由. 在CALayer有一個叫conrnerRadius的CGFloat類型屬性來控制着圖層角的曲率, 默認值爲0, 你能夠設置任意數值, 是的圖層角顯示不同的曲率, 並且conrnerRadius這個屬性所影響的到的只有設置該屬性的CALayer, 並不會影響到子圖層或者是背景圖, 但若是你要讓子圖層或者是背景圖也要跟着該CALayer進行曲率處理, 你能夠把masksToBounds設置爲YES, 這樣子就能夠知足你的需求了. 咱們直接來看看Demo吧:express

- (void)layerRoundedCorners {
    
    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
    
    view.backgroundColor = [UIColor redColor];
    view.layer.cornerRadius = 50.f;
    view.layer.masksToBounds = YES;
    
    CALayer *layer = [CALayer layer];
    
    layer.backgroundColor = [UIColor blueColor].CGColor;
    layer.frame = CGRectMake(50, 50, 50, 50);
    
    [view.layer addSublayer:layer];
    [self.view addSubview:view];
}
複製代碼

1

2

PS: 這裏須要注意一點, 因爲masksToBoundsconrnerRadius這兩個屬性同時使用是挺消耗性能的, 若是你是要大面積的去使用, 會形成卡頓現象, 好比說在UICollectionView或者是UITableView上使用.微信


Layer Borders

CALayer還有兩個更好玩的屬性, 這也是在iOS 7以前Button會默認實現的兩個屬性, 一個叫作borderWidth, 一個叫作borderColor. 佈局

  • borderWidth: 這是一個CGFloat類型的屬性, 是用來設置CALayer邊框寬度, 默認值是爲0.
  • borderColor: 這是一個CGColorRef類型的屬性, 因此你不能給它直接設置一個UIColor對象, 前面咱們已經對CGColorRef這個東東進行了簡單的介紹, 這裏咱們只須要知道直接給它賦個值就行了, 還有就是borderColor是用來設置CALayer邊框顏色, 在iOS 7以前默認值是爲黑色, iOS 7以後默認值是爲透明.
咱們直接來看Demo吧:
- (void)layerBorders {
    
    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
    
    view.backgroundColor = [UIColor blueColor];
    view.layer.borderWidth = 5.f;
    view.layer.borderColor = [UIColor redColor].CGColor;
    
    [self.view addSubview:view];
}
複製代碼

3

4


Drop Shadows

iOS當中, 還有一個特性, 叫作Drop Shadows(陰影), 其實這個也不算是iOS特有的, 畢竟在Mac OS裏早就已經有這個特性了. 陰影每每是起暗示做用, 好比說你如今正在顯示的窗口, 周邊就會帶上陰影, 或者是強調裏面的某個圖層的優先級, 大多數時候只是用來裝飾罷了. 設置陰影的時候也是很簡單, 直接給shadowOpacity屬性設置一個大於0.0的值就行了, shadowOpacity這個屬性可設置的值是在0.0~1.0之間, 默認是0.f, 最大值是1.f, 若是直接設置爲1.f, 那麼將會顯示一個輕微模糊的黑色陰影在圖層的上方, 另外, 你能夠經過CALayer所提供的shadowColor, shadowOffset, shadowRadius對陰影進行一些額外的操做, 這裏就不一一介紹了, 各位童鞋們能夠自行嘗試一下~ 說到這裏, 會有人問, 爲何陰影是在圖層的上方呢? 其實在以前咱們就有了解過Mac OS和iOS的一些東西, 基本上iOS的一些東西都是從Mac OS搬過來, 而後再改改的, 包括這個陰影也是如此, 因此你纔會看到在iOS當中陰影是反過來的, 這裏咱們只須要設置一下shadowOffset就能夠正常顯示了. 直接看Demo吧:性能

- (void)layerDropShadows {
    
    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
    
    view.backgroundColor = [UIColor redColor];
    view.layer.shadowOpacity = 1.0f;
    view.layer.shadowOffset = CGSizeMake(0, 3);
    view.layer.shadowRadius = 10.f;
    view.layer.shadowColor = [UIColor blueColor].CGColor;
    
    [self.view addSubview:view];
}
複製代碼

5

6

Shadow Clipping

這裏還有一個比較好玩的東西, 就是陰影剪切, 咱們都知道CALayer超出了UIView的範圍, 若是要剪切掉的話, 只能用masksToBounds這個屬性去剪切. 但這樣子會帶來另外一個的問題, 由於一旦使用masksToBounds這個屬性, 剪切掉的就不僅是多出來的部分, 會連陰影部分都一塊兒剪切完, 爲了防止陰影也跟着被剪切掉, 咱們須要使用一個比較笨的方法, 就是再建立多一個CALayer, 讓它去建立陰影部分, 另外一個CALayer去剪切內容就能夠了. 咱們仍是直接看Demo吧:學習

- (void)layerShadowClipping {
    
    UIView *contentView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
    UIView *blueView = [[UIView alloc] initWithFrame:CGRectMake(50, 50, 100, 100)];
    UIView *shadowView = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
    
    contentView.backgroundColor = [UIColor grayColor];
    blueView.backgroundColor = [UIColor blueColor];
    
    contentView.layer.masksToBounds = YES;
    
    shadowView.layer.shadowOpacity = 1.0f;
    shadowView.layer.shadowOffset = CGSizeMake(0, 0.5f);
    shadowView.layer.shadowColor = [UIColor redColor].CGColor;

    [contentView addSubview:blueView];
    [shadowView addSubview:contentView];
    
    [self.view addSubview:shadowView];
}
複製代碼

7

8

shadowPath

咱們都知道其實陰影是沒有形態的, 它是根據圖層的形狀來進行顯示, 若是在一個視圖當中有不少子圖層, 而後要一個一個的去計算陰影的形狀, 那是很是耗性能的, 但若是在開發以前你就已經知道陰影的形狀, 那麼你就能夠提早設置好, 這樣子就能夠優化性能了, 而這個屬性就是shadowPath, shadowPathCGPathRef類型, 能夠說是一個指向CGPath的指針, 而CGPath是一個Core Graphics對象, 能夠用來任意描繪一個矢量圖形, 咱們也可使用它來描繪陰影, 大大的提高性能. 咱們直接來看Demo吧:優化

- (void)layerShadowPath {
    
    UIView *shadowViewOne = [[UIView alloc] initWithFrame:CGRectMake(50, 50, 100, 100)];
    UIView *shadowViewTwo = [[UIView alloc] initWithFrame:CGRectMake(50, 250, 100, 100)];

    shadowViewOne.layer.shadowOpacity = 0.5f;
    shadowViewTwo.layer.shadowOpacity = 0.5f;
    
    CGMutablePathRef squarePath = CGPathCreateMutable();
    CGPathAddRect(squarePath, NULL, shadowViewOne.bounds);
    shadowViewOne.layer.shadowPath = squarePath;
    
    CGPathRelease(squarePath);
    
    CGMutablePathRef circlePath = CGPathCreateMutable();
    CGPathAddEllipseInRect(circlePath, NULL, shadowViewTwo.bounds);
    shadowViewTwo.layer.shadowPath = circlePath;
    
    CGPathRelease(circlePath);

    [self.view addSubview:shadowViewOne];
    [self.view addSubview:shadowViewTwo];
}
複製代碼

9

10


Layer Masking

咱們都知道若是咱們要剪切超出範圍的圖層可使用masksToBounds, 經過conrnerRadius能夠設置圖層爲圓角, 但若是你須要設置一個不規整的圖層時, 用上面的兩個屬性是無法實現的. 雖然咱們可使用一個32位且帶有alpha通道的png圖片能夠實現, 但這個方法也是有侷限的, 不能以動態編碼的形式生成蒙版, 也不能讓子圖層或者子視圖也裁剪成一樣的形狀. 蘋果爲了解決這個爲題, 在CALayer當中提供了一個CGLayer類型, 名叫mask的屬性, 有着和其餘CALayer同樣的佈局屬性, 它就像是一個子圖層, 相對於父圖層來進行佈局的, 但它又區別於子圖層, 它是定義父圖層可見部分的. 雖然mask裏也有Color這個屬性, 但它並沒啥用, 真正重要的是圖層的輪廓, 它就像是一臺切割機同樣, 實心圖層部分會被保留, 其餘的就會做爲垃圾同樣被拋棄. 咱們直接來看Demo吧:ui

- (void)layerMasking {
    
    UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
    
    imageView.image = [UIImage imageNamed:@"arrow"];
    
    CALayer *maskLayer = [CALayer layer];
    UIImage *maskImage = [UIImage imageNamed:@"star"];
    
    maskLayer.frame = imageView.bounds;
    maskLayer.contents = (__bridge id _Nullable)(maskImage.CGImage);
    
    imageView.layer.mask = maskLayer;
    
    [self.view addSubview:imageView];
}
複製代碼

11

12


Scaling Filters

這裏咱們說起一個點, 是關於圖片顯示的一個問題, 咱們都知道若是要讓一個CALayer顯示一張圖片是直接給它的contents直接設置內容, 可是呢, 這個圖片是否正確的顯示, 畫質如何, 咱們都無從而知. 爲了解決這個問題,CALayer分別提供了minificationFiltermagnificationFilter屬性, 它們都是NSString類型, 說到這裏, 有人會疑問, 直接顯示不就是最好的麼, 爲啥要那麼麻煩, 其實不必定的, 緣由的話, 大概有三點吧:

  • 可以顯示最好的畫質, 指的是像素沒有被壓縮也沒有被拉伸.
  • 能夠節省資源, 好比神馬內存, 存儲之類的.
  • 能夠優化性能, 減輕CPU的壓力.

打個比方, 好比咱們開發的時候, 有個頭像省略圖, 這個時候呢, 你說是用全圖比較好, 仍是壓縮過的比較好? 答案確定是壓縮過的比較好, 由於能夠省資源. 順便說說, 這兩個屬性可設置的值分別是:

  • kCAFilterLinear(默認值)
  • kCAFilterNearest
  • kCAFilterTrilinear 說那麼多, 直接來看Demo吧:
- (void)layerScalingFilters {
    
    UIImageView *imageViewOne = [[UIImageView alloc] initWithFrame:CGRectMake(0, 100, self.view.bounds.size.width / 2, 200)];
    UIImageView *imageViewTwo = [[UIImageView alloc] initWithFrame:CGRectMake(self.view.bounds.size.width / 2, 100, self.view.bounds.size.width / 2, 200)];
    UIImageView *imageViewThree = [[UIImageView alloc] initWithFrame:CGRectMake(0, 300, self.view.bounds.size.width / 2, 200)];
    
    imageViewOne.image = [UIImage imageNamed:@"expression"];
    imageViewTwo.image = [UIImage imageNamed:@"expression"];
    imageViewThree.image = [UIImage imageNamed:@"expression"];

    imageViewOne.layer.magnificationFilter = kCAFilterNearest;
    imageViewTwo.layer.magnificationFilter = kCAFilterLinear;
    imageViewThree.layer.magnificationFilter = kCAFilterTrilinear;

    imageViewOne.layer.minificationFilter = kCAFilterNearest;
    imageViewTwo.layer.minificationFilter = kCAFilterLinear;
    imageViewThree.layer.minificationFilter = kCAFilterTrilinear;
    
    [self.view addSubview:imageViewOne];
    [self.view addSubview:imageViewTwo];
    [self.view addSubview:imageViewThree];
}
複製代碼

13

14

額...這個有些尷尬, 看起來的效果區別不太大...湊合着看吧..


Group Opacity

最後, 咱們來講說Group Opacity這個東西, 在iOS 7以前, 若是你在一個Button上添加一個視圖, 在alpha設置爲50%的狀況下會出現圖層有分割, 須要設置shouldRasterizerasterizationScale兩個屬性才能使得在半透明的狀況下看起來是一體, 可是這個問題在iOS 7以後就已經解決了, 如今shouldRasterize屬性更多的是用來解決UITableView裏的CALayer圓角顯示圖層的處理, 這裏就不作多的解釋了, 有興趣的童鞋們能夠去谷歌搜搜shouldRasterize的用法, 都是挺簡單的~


總結

總結一下, 這一章咱們瞭解更多的是CALayer肉眼上能看到的東西, 好比:

  • Rounded Corners: 在這個知識點裏, 咱們瞭解了CALayer圓角的處理.
  • Layer Borders: 在這個知識點裏, 咱們瞭解了CALayer邊框的處理, 包括邊框的厚度, 以及顏色等
  • Drop Shadows: 在這個知識點裏, 咱們知道了CALayer陰影的處理.
  • Layer Masking: 在這個知識點裏, 咱們瞭解了CALayer能夠做爲一個mask去使用, 而且能夠顯示不一樣不規則的形狀.
  • Scaling Filters: 在這個知識點裏, 咱們知道CALayer能夠更改顯示的畫質, 優化顯示的資源等等.
  • Group Opacity: 在這個知識點裏, 雖然在iOS 7以後已經解決了這個問題, 但咱們也能夠把shouldRasterize屬性運用在其餘的地方.

工程地址

項目地址: https://github.com/CainRun/CoreAnimation


最後

碼字很費腦, 看官賞點飯錢可好

微信

支付寶
相關文章
相關標籤/搜索