iOS 離屏渲染

從設置圓角開始

咱們知道,通常圓角效果會開啓離屏渲染,可是並不是所用的圓角都會開啓離屏渲染。那麼問題來了:什麼狀況下的圓角效果纔會開啓離屏渲染呢?緩存

先來看一下,蘋果官方文檔對圓角(cornerRadius)的說明:app

Setting the radius to a value greater than 0.0 causes the layer to begin drawing 
rounded corners on its background. By default, the corner radius does not apply to 
the image in the layer’s contents property; it applies only to the background color 
and border of the layer. However, setting the masksToBounds property to YES causes 
the content to be clipped to the rounded corners.
The default value of this property is 0.0.
複製代碼

意思大概是:在cornerRadius設置的值大於 0.0 的時候會使 layer 在背景上繪製圓角,默認狀況下,圓角效果並不會影響到 layer 的 contents 屬性中的 image;它只會影響 layer 的背景顏色和邊框。可是設置 masksToBounds 屬性爲 YES 會致使 content 被剪裁出圓角。性能

通常在設置了圓角以後,咱們會設置 clipsToBounds 或者 masksToBounds 來剪裁掉多餘的部分。clipsToBounds 指視圖上的子視圖,若是超出父視圖的部分就截取掉;masksToBounds 是指視圖的圖層上的子圖層,若是超出父圖層的部分就截取掉。this

tips:在模擬器打開離屏渲染顏色標記

在模擬器打開離屏渲染顏色標記

注:本例中海綿寶寶圖片(btn.png)尺寸爲557 × 409 pixels;皮卡丘圖片(testIcon.png)尺寸爲64 × 64 pixels

先看下面的代碼:spa

//1.按鈕存在背景圖片
    UIButton *btn1 = [UIButton buttonWithType:UIButtonTypeCustom];
    btn1.frame = CGRectMake(50, 100, 100, 100);
    btn1.layer.cornerRadius = 50;
    [self.view addSubview:btn1];
    [btn1 setImage:[UIImage imageNamed:@"btn.png"] forState:UIControlStateNormal];
    btn1.clipsToBounds = YES;
    
    //2.按鈕不存在背景圖片
    UIButton *btn2 = [UIButton buttonWithType:UIButtonTypeCustom];
    btn2.frame = CGRectMake(50, 250, 100, 100);
    btn2.layer.cornerRadius = 50;
    btn2.backgroundColor = [UIColor blueColor];
    [self.view addSubview:btn2];
    btn2.clipsToBounds = YES;

    
    //3.UIImageView 設置了圖片+背景色;
    UIImageView *img3 = [[UIImageView alloc]init];
    img3.frame = CGRectMake(50, 400, 100, 100);
    img3.backgroundColor = [UIColor blueColor];
    [self.view addSubview:img3];
    img3.layer.cornerRadius = 50;
    img3.layer.masksToBounds = YES;
    img3.image = [UIImage imageNamed:@"btn.png"];

    
    //4.UIImageView 只設置了圖片,無背景色;
    UIImageView *img4 = [[UIImageView alloc]init];
    img4.frame = CGRectMake(50, 550, 100, 100);
    [self.view addSubview:img4];
    img4.layer.cornerRadius = 50;
    img4.layer.masksToBounds = YES;
    img4.image = [UIImage imageNamed:@"btn.png"];
複製代碼

代碼運行效果以下: code

離屏渲染展現圖1

從圖上能夠看到第一個和第三個海綿寶寶都觸發了離屏渲染。orm

那麼再來看下面的代碼:cdn

//1.按鈕存在背景圖片
    UIButton *btn1 = [UIButton buttonWithType:UIButtonTypeCustom];
    btn1.frame = CGRectMake(50, 100, 100, 100);
    btn1.layer.cornerRadius = 50;
    [self.view addSubview:btn1];
    [btn1 setImage:[UIImage imageNamed:@"btn.png"] forState:UIControlStateNormal];
    btn1.clipsToBounds = YES;
    
    //1.按鈕存在背景圖片
    UIButton *btn11 = [UIButton buttonWithType:UIButtonTypeCustom];
    btn11.frame = CGRectMake(200, 100, 100, 100);
    btn11.layer.cornerRadius = 50;
    [self.view addSubview:btn11];
    [btn11 setImage:[UIImage imageNamed:@"testIcon.png"] forState:UIControlStateNormal];
    btn11.clipsToBounds = YES;
複製代碼

代碼運行效果以下:blog

離屏渲染展現圖2

最後再來一段代碼:圖片

//1.按鈕存在背景圖片
    UIButton *btn1 = [UIButton buttonWithType:UIButtonTypeCustom];
    btn1.frame = CGRectMake(50, 100, 100, 100);
    btn1.layer.cornerRadius = 50;
    [self.view addSubview:btn1];
    [btn1 setImage:[UIImage imageNamed:@"btn.png"] forState:UIControlStateNormal];
    btn1.clipsToBounds = YES;
    
    //1.按鈕存在背景圖片
    UIButton *btn11 = [UIButton buttonWithType:UIButtonTypeCustom];
    btn11.frame = CGRectMake(200, 100, 100, 100);
    btn11.layer.cornerRadius = 50;
    [self.view addSubview:btn11];
    [btn11 setImage:[UIImage imageNamed:@"testIcon.png"] forState:UIControlStateNormal];
    btn11.clipsToBounds = YES;
    [btn11 sizeToFit];
複製代碼

代碼運行效果以下:

離屏渲染展現圖3

比較上面三段代碼和三張圖片,繪製圓角的時候什麼狀況下回觸發離屏渲染。

爲何須要離屏渲染

有些渲染效果沒法一次完成,須要將渲染的中間結果保存在離屏緩衝區,等到最後將全部的保存的渲染結果一塊兒合成爲最終的渲染效果。

對於能夠複用的一些渲染效果,能夠保存在離屏緩衝區已提升性能。

沒法一次完成的渲染效果

好比圓角這樣的效果,當有多個圖層時,每一個圖層都須要作圓角、剪裁時,就須要分別對每一個圖層作處理,從最底層的圖層開始,一直到最頂層的圖層。

前面咱們說了只有在設置圓角後開啓了clipsToBounds或者masksToBounds的時候纔會觸發離屏渲染。

在離屏渲染展現圖1中:前兩個控件是 UIButton(注意:UIButton是有多個圖層的),後兩個控件是 UIImageView。第一個控件先要對背景顏色和邊框作圓角處理,而後再對圖片作圓角處理;第二個控件沒有設置圖片,只須要對背景顏色和邊框作圓角處理就行了;第三個控件設置了背景顏色和圖片,一樣的也先要對背景顏色和邊框作圓角處理,而後對圖片作圓角處理;最後一個空間只只設置了背景顏色,也只須要對背景顏色和邊框作圓角處理。

再看離屏渲染展現圖2中:兩個空間都是 UIButton。兩個 UIButton 除了設置的圖片不同之外,其餘設置都是同樣的。能夠看到皮卡丘這個按鈕並無觸發離屏渲染。控件添加的圖片尺寸小於控件的 frame,這時候不須要對圖片進行剪裁,也不會觸發離屏渲染。

最後咱們看一看離屏渲染展現圖2中,對皮卡丘這個按鈕運行了sizeToFit方法後,發現又觸發了離屏渲染。是否是很神奇。這個時候皮卡丘這個按鈕的 frame 被 重置了,適應了圖片的大小。這個時候再設置圓角就要處理背景顏色和邊框以及圖片了。

複用的渲染效果

看下面的代碼

//4.UIImageView 只設置了圖片,無背景色;
    UIImageView *img4 = [[UIImageView alloc]init];
    img4.frame = CGRectMake(50, 550, 100, 100);
    [self.view addSubview:img4];
    img4.layer.cornerRadius = 50;
    img4.layer.masksToBounds = YES;
    img4.image = [UIImage imageNamed:@"btn.png"];
    
    //4.UIImageView 只設置了圖片,無背景色;
    UIImageView *img44 = [[UIImageView alloc]init];
    img44.frame = CGRectMake(200, 550, 100, 100);
    [self.view addSubview:img44];
    img44.layer.cornerRadius = 50;
    img44.layer.masksToBounds = YES;
    img44.image = [UIImage imageNamed:@"btn.png"];
    img44.layer.shouldRasterize = YES;
複製代碼

代碼執行效果以下:

光柵化觸發離屏渲染圖 4

從代碼裏,咱們能夠看到兩個海綿寶寶的惟一區別就是第二個海綿寶寶設置了光柵化(shouldRasterize)。咱們倆看看那蘋果對光柵化是怎麼說的:

When the value of this property is YES, the layer is rendered as a bitmap in its 
local coordinate space and then composited to the destination with any other 
content. 
複製代碼

當這個值被設置爲 YES 時,layer 會在它的本地座標控件被渲染成一個位圖,而後與其餘任何內容合成爲目標。這個被渲染出來的位圖會被緩存起來。

上面就是我對離屏渲染的實踐和理解,若有疏漏,請留言。

相關文章
相關標籤/搜索