离屏渲染浅析

2020-07-08  本文已影响0人  源本平凡

1. 普通渲染

2. 离屏渲染

2.1 影响

2.2 使用原因

情况1

圆角处理:

设置圆角为什么会触发离屏渲染呢?这个要从layer的结构说起。
layer结构中包含3部分:
backgroundColor
contents
boarder相关信息(borderWidth和borderColor)

设置圆角代码,这个大家应该都知道:

view.layer.cornerRadius = 1

我们先看看官方文档中cornerRadius相关说明:


cornerRadius.png

Discussion中的说明:
设置cornerRadius超过0.0,不会影响contents,但是会影响background color和border。如果设置了masksToBounds会对content进行裁剪。
所以说触发离屏渲染的主要原因:

masksToBounds=YES;

这就是模拟器开启离屏渲染模式中说明的为什么要设置masksToBounds的原因。masksToBounds需要对layer上的所有内容进行裁剪,过程中需要对中间值进行保存。所以进行了离屏渲染操作。
注意:
如果说layer图层比较简单,也是不会触发离屏渲染的。例如:UIImageView设置cornerRadius和masksToBounds是不会触发离屏渲染的,如果再对UIImageView设置背景色,则会触发。

    self.view.backgroundColor = [UIColor grayColor];
    
    UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"1"]];
    imageView.frame = CGRectMake(100, 100, 100, 100);
    imageView.layer.cornerRadius = 30;
    imageView.layer.masksToBounds = YES;
    [self.view addSubview:imageView];
    
    UIImageView *imageView2 = [[UIImageView alloc]  initWithImage:[UIImage imageNamed:@"1"]];
    imageView2.backgroundColor = UIColor.redColor;
    imageView2.frame = CGRectMake(100, 250, 100, 100);
    imageView2.layer.cornerRadius = 30;
    imageView2.layer.masksToBounds = YES;
    [self.view addSubview:imageView2];
    
    UIButton *btn = [UIButton   buttonWithType:UIButtonTypeCustom];
    [btn setBackgroundImage:[UIImage imageNamed:@"1"]   forState:UIControlStateNormal];
    btn.layer.cornerRadius = 30;
    btn.layer.masksToBounds = YES;
    btn.frame = CGRectMake(100, 400, 100, 100);
    [self.view addSubview:btn];

代码中有三个控件,前两个是UIImageView,最后一个是UIButton。

第一个UIImageView设置了图片没有设置背景色,没有触发离屏渲染。
第二个UIImageView设置了图片和背景色,触发了离屏渲染。
最后一个UIButton,设置图片没有设置背景色,触发了离屏渲染。原因是我们看到UIButton是由它的layer和UIImageView的layer混合起来的效果(UIButton有imageView),所以设置圆角的时候会触发离屏渲染。

情况2

shouldRasterize使用建议:

layer不复用,没必要使用shouldRasterize;
layer不是静态的,也就是说要频繁的进行修改,没必要使用shouldRasterize;
时间方面:离屏渲染缓存有100ms时间限制,超过该时间的内容会被丢弃,进而不能达到复用的目的;
空间方面:离屏渲染空间是屏幕像素的2.5倍,如果超过也无法复用。

2.3 如何避免

  1. 直接更换资源,让UI提供带圆角的图片。
  2. 使用layer.mask属性,增加一个和背景色相同的遮罩覆盖上层,盖住四个角,营造出圆角的形状。但这种方式难以解决背景色为图片或渐变色的情况。
  3. 使用贝塞尔曲线绘制闭合圆角的矩形,在上下文中设置只有内部可见,再将不带圆角的 layer 渲染成图片,添加到贝塞尔矩形中。这种方法效率更高,但是 layer 的布局一旦改变,贝塞尔曲线都需要手动地重新绘制,所以需要对 frame、color 等进行手动地监听并重绘。
  4. CoreGraphics重写 drawRect:,用 CoreGraphics 相关方法,在需要应用圆角时进行手动绘制。不过 CoreGraphics 效率也很有限,如果需要多次调用也会有效率问题。

2.4 产生原因总结

上一篇 下一篇

猜你喜欢

热点阅读