设置圆角的4种方式--引申出离屏渲染
#pragma mark - 三、圆角问题4种
第一种:设置cornerRadius masksToBounds = yes,会引起离屏渲染
// UIImageView * imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"imageName1.jpg"]]; // [imageView setFrame: CGRectMake(100, 100, 50, 50)]; // imageView.layer.cornerRadius = 5; // //裁剪掉超出的 // imageView.layer.masksToBounds = YES; // [self.view addSubview:imageView]; // // UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom]; // [button setImage:[UIImage imageNamed:@"imageName2.jpg"] forState:UIControlStateNormal]; // [button setFrame:CGRectMake(100, 180, 50, 50)]; // button.layer.cornerRadius = 10; // button.layer.masksToBounds = YES; // [self.view addSubview:button];
第二种:使用贝塞尔曲线UIBezierPath和Core Graphics框架在图片的绘图上下文中画出一个透明的圆,增加CPU负担,增加内存开销
// UIImageView *imageViewTwo = [[UIImageView alloc]initWithFrame:CGRectMake(100, 100, 100, 100)]; // imageViewTwo.image = [UIImage imageNamed:@"imageName1.jpg"]; // //开始对imageView进行画图,在透明的这个imageView的画布上开始画 // UIGraphicsBeginImageContextWithOptions(imageViewTwo.bounds.size, NO, [UIScreen mainScreen].scale); //// UIGraphicsBeginImageContextWithOptions(<#CGSize size#>, <#BOOL opaque#>, <#CGFloat scale#>) // //opaque:不透明 // //使用贝塞尔曲线画出一个圆形图,并且切掉其他的,就剩下了透明的想要的那个圆 // [[UIBezierPath bezierPathWithRoundedRect:imageViewTwo.bounds cornerRadius:imageViewTwo.frame.size.width] addClip]; //// + (instancetype)bezierPathWithRoundedRect:(CGRect)rect cornerRadius:(CGFloat)cornerRadius; // //rounds all corners with the same horizontal and vertical radius // [imageViewTwo drawRect:imageViewTwo.bounds]; // // imageViewTwo.image = UIGraphicsGetImageFromCurrentImageContext(); // //结束画图 // UIGraphicsEndImageContext(); // [self.view addSubview:imageViewTwo];
第三种:使用CAShapeLayer和UIBezierPath设置圆角,设置view.layer.mask,同样会触发离屏渲染。
// UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(100, 100, 100, 100)]; // imageView.image = [UIImage imageNamed:@"imageName1.jpg"]; // // UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:imageView.bounds byRoundingCorners:UIRectCornerAllCorners cornerRadii:imageView.bounds.size]; // // CAShapeLayer *maskLayer = [[CAShapeLayer alloc]init]; // //设置大小 // maskLayer.frame = imageView.bounds; // //设置图形样子 // maskLayer.path = maskPath.CGPath; // imageView.layer.mask = maskLayer; // // [self.view addSubview:imageView];
第四种:混合图层,两个图叠加在一起
用另外一个imageView盖在上面
另引申出:Off-Screen Rendering离屏渲染
是GPU在当前屏幕缓冲区以外新开辟一个缓冲区进行渲染操作。
offscreen-render有两种形式:
CPU的offscreen-render
使用CPU来完成渲染操纵,通常在你使用:
- drawRect (如果没有自定义绘制的任务就不要在子类中写一个空的drawRect方法,因为只要实现了该方法,就会为视图分配一个寄宿图,这个寄宿图的像素尺寸等于视图大小乘以 contentsScale的值,造成资源浪费)
- 使用Core Graphics
上面的两种情况使用的就是CPU离屏渲染,首先分配一块内存,然后进行渲染操作生成一份bitmap位图,整个渲染过程会在你的应用中同步的进行,接着再将位图打包发送到iOS里一个单独的进程--render server,理想情况下,render server将内容交给GPU直接显示到屏幕上。
GPU(Graphic Processing Unit)的offscreen-render
使用GPU在当前屏幕缓冲区以外开辟一个新的缓冲区进行绘制,通常发生的情况有:
- 设置cornerRadius, masks, shadows,edge antialiasing等
- 设置layer.shouldRasterize = YES
shouldRasterize打开
在触发离屏绘制的同时,会将光栅化后的内容缓存起来,如果对应的layer及其sublayers没有发生改变,在下一帧的时候可以直接复用。这将在很大程度上提升渲染性能。