iOS的阴影绘制及性能优化
今天来讲讲iOS
开发过程中的阴影绘制及其潜在的绘图性能问题。虽然在开发过程中,我们使用阴影功能的机会不是很多,但是如果用了,有可能引起如卡顿等性能问题,所以,还是有必要来探究一下阴影的绘制过程,及如何提高阴影的绘制性能。
阴影绘制
阴影可以通过设置layer
层的shadowXXX
属性,就可以很方便的为UIView
添加阴影效果,但是不同的设置方式可能产生性能方面的问题,下面介绍一下不同方式对性能的影响。
方式一
通过设置下面的4个属性,就可以添加阴影,这种方式可能产生性能问题,因为绘制阴影而不指定阴影路径,在绘制阴影过程中,就会产生大量的离屏渲染(Offscreen-Rendered
),非常消耗性能,进而造成动画卡顿的问题。
离屏渲染
造成离屏渲染的原因很多,比如:遮罩、阴影、抗锯齿等等,而阴影造成离屏渲染的原因是:iOS
会先绘制目标的阴影,然后绘制目标的本身,在没有指定阴影的绘制路径时,iOS
视图在每次绘制前都会递归的精确计算每个子层阴影的路径,这会非常消耗性能,也是导致卡顿的根源。
所以,如果绘制的阴影不是很多的情况下,该方法不会消耗大量性能,绘制就会比较简单,代码量也少。
// 设置阴影颜色
self.imageView1.layer.shadowColor = [UIColor orangeColor].CGColor;
// 设置阴影的偏移量,默认是(0, -3)
self.imageView1.layer.shadowOffset = CGSizeMake(4, 4);
// 设置阴影不透明度,默认是0
self.imageView1.layer.shadowOpacity = 0.8;
// 设置阴影的半径,默认是3
self.imageView1.layer.shadowRadius = 4;
方式二
为了减少因为没有设置shadowPath
造成绘制阴影时大量重复绘制的问题,我们可以指定阴影的绘制路径,这样在绘制阴影时,就可以在多个layer
层共享同一个路径的阴影,以此来提高性能,下面是苹果官方文档是解释:
/* When non-null this path defines the outline used to construct the
* layer's shadow instead of using the layer's composited alpha
* channel. The path is rendered using the non-zero winding rule.
* Specifying the path explicitly using this property will usually
* improve rendering performance, as will sharing the same path
* reference across multiple layers. Upon assignment the path is copied.
* Defaults to null. Animatable. */
@property(nullable) CGPathRef shadowPath;
shadowPath
的注释大意就是说如果不指定路径,就会使用layer
层的alpha
通道的混合,而如果指定阴影路径,就会在多个layer
层之间共享同一路径,以此来提高性能。
有关什么是layer
层的混合,可以这样理解:iOS
在渲染每一帧时,都会计算每一个像素的颜色,如果上层layer
不透明,就只取上层layer
的颜色;而如果上层layer
存在透明度时(alpha通道),则需要混合每一层的颜色来计算最终的颜色。如果layer
越多,计算量就越大,也就比较耗性能。所以,在开发中,要尽量减少视图的透明层。
具体代码示例,具体是功能就是绘制一个边框阴影:
_imageView.layer.shadowColor = [UIColor yellowColor].CGColor;//shadowColor阴影颜色
_imageView.layer.shadowOffset = CGSizeMake(0,0);//shadowOffset阴影偏移,默认(0, -3),这个跟shadowRadius配合使用
_imageView.layer.shadowOpacity = 1;//阴影透明度,默认0
_imageView.layer.shadowRadius = 3;//阴影半径,默认3
//路径阴影
UIBezierPath *path = [UIBezierPath bezierPath];
float width = _imageView.bounds.size.width;
float height = _imageView.bounds.size.height;
float x = _imageView.bounds.origin.x;
float y = _imageView.bounds.origin.y;
float addWH = 10;
CGPoint topLeft = _imageView.bounds.origin;
CGPoint topMiddle = CGPointMake(x+(width/2),y-addWH);
CGPoint topRight = CGPointMake(x+width,y);
CGPoint rightMiddle = CGPointMake(x+width+addWH,y+(height/2));
CGPoint bottomRight = CGPointMake(x+width,y+height);
CGPoint bottomMiddle = CGPointMake(x+(width/2),y+height+addWH);
CGPoint bottomLeft = CGPointMake(x,y+height);
CGPoint leftMiddle = CGPointMake(x-addWH,y+(height/2));
[path moveToPoint:topLeft];
//添加四个二元曲线
[path addQuadCurveToPoint:topRight
controlPoint:topMiddle];
[path addQuadCurveToPoint:bottomRight
controlPoint:rightMiddle];
[path addQuadCurveToPoint:bottomLeft
controlPoint:bottomMiddle];
[path addQuadCurveToPoint:topLeft
controlPoint:leftMiddle];
//设置阴影路径
_imageView.layer.shadowPath = path.CGPath;
综上,以后开发过程中,如果用到阴影效果,在视图图层不是很多,阴影视图计算量少的情况下,可以直接设置阴影,但是如果图层较多,阴影的计算量较大,则要考虑使用path
的方式。(本文主要参考互联网,版本归原作者所有)
参考资料
iOS的阴影绘制及性能优化的更多相关文章
- iOS性能优化-异步绘制
参考地址:https://blog.ibireme.com/2015/11/12/smooth_user_interfaces_for_ios/ 很久以前就看过这篇文章,但是也只是看过就过了,没有去整 ...
- iOS程序性能优化
iOS程序性能优化 一.初级 使用ARC进行内存管理 在iOS5发布的ARC,它解决了最常见的内存泄露问题.但是值得注意的是,ARC并不能避免所有的内存泄露.使用ARC之后,工程中可能还会有内存泄露, ...
- iOS 程序性能优化
前言 转载自:http://www.samirchen.com/ios-performance-optimization/ 程序性能优化不应该是一件放在功能完成之后的事,对性能的概念应该从我们一开始写 ...
- [iOS Animation]-CALayer 性能优化
性能优化 代码应该运行的尽量快,而不是更快 - 理查德 在第一和第二部分,我们了解了Core Animation提供的关于绘制和动画的一些特性.Core Animation功能和性能都非常强大,但如果 ...
- iOS进阶之页面性能优化
转载:http://www.jianshu.com/p/1b5cbf155b31 前言 在软件开发领域里经常能听到这样一句话,"过早的优化是万恶之源",不要过早优化或者过度优化.我 ...
- iOS 性能优化总结
卡顿产生的原因 在 VSync信号到来后,系统图形服务会通过 CADisplayLink等机制通知 App,App主线程开始在 CPU中计算显示内容,比如视图的创建.布局计算.图片解码.文本绘制等.随 ...
- iOS页面性能优化
前言 在软件开发领域里经常能听到这样一句话,“过早的优化是万恶之源”,不要过早优化或者过度优化.我认为在编码过程中时刻注意性能影响是有必要的,但凡事都有个度,不能为了性能耽误了开发进度.在时间紧急的情 ...
- iOS开发系列之性能优化(上)
本篇主要记录一下我对界面优化上的一些探索.关于时间优化的探索将会在中篇里进行介绍.下篇将主要介绍一些耗电优化.安装包瘦身的探索. ### 1.卡顿原理 要了解卡顿原理,需要对帧缓冲区.垂直同步.CPU ...
- iOS性能优化-数组、字典便利时间复杂
上图是几种时间复杂度的关系,性能优化一定程度上是为了降低程序执行效率减低时间复杂度. 如下是几种时间复杂度的实例: O(1) return array[index] == value; 复制代码 O( ...
随机推荐
- Educational Codeforces Round 22.B 暴力
B. The Golden Age time limit per test 1 second memory limit per test 256 megabytes input standard in ...
- JavaScript第三课 (循环)
循环语句 !如果至少需要执行一次循环体,就用do … while语句,一般情况下用while语句就可以了. while 语法:一直读取循环到条件为假时停止循环. while(条件) { 语 ...
- C#获取数据库连接字符
有两种用法:1)using System.Configuraiton; string ConStr=ConfigurationManager.ConnectionStrings["ConSt ...
- 包装类、数组、string类浅析及练习
String s1 = "abc"; String s2 = "abc"; System.out.println(s1==s2); //返回true Strin ...
- 【PHP】PHP面向对象编程--phpOOP入门
PHP从入门到精通 之PHP的面相对象编程 面向对象编程(Object Oriented Programming, OOP, 面向对象程序设计)是一种计算机编程架构,OOP的一条基本原则是计算机程序 ...
- 【转载】DHCP流程
来源: http://network.51cto.com/art/201406/441752.htm DHCP是一个局域网的网络协议,使用UDP协议工作,主要有两个用途:给内部网络或网络服务供应商自动 ...
- Linux 如何显示一个文件的某几行
1. 从第1000行开始,显示2000行.即显示1000~2999行 cat input_file | tail -n +1000 | head -n 2000 2. 显示 1000行到3000行 c ...
- css3关键帧动画实现轮播效果
实现效果:打开手机京东,可以看到首页的头部,以这个头部为基础,仿写一个类似的样式. 思路:仔细观察可以发现,手机京东的头部是以一个搜索栏和轮播特效组成的,而这个搜索栏是以轮播特效做为背景的,现在运用c ...
- 初学Python(一)——数据类型
初学Python(一)——数据类型 初学Python,主要整理一些学习到的知识点,这次是数据类型. #-*- coding:utf-8 -*- #整数 print 1 #浮点数=小数 print 1. ...
- 小白浅论JAVA数组中“for加强版”
代码: /*String[] s=new String[]{"sdsfd","fgd","sdf"}; for(String a:s) Sy ...