iOS 之使用CAShapeLayer中的CAGradientLayer实现圆环的颜色渐变

来源:互联网 发布:艺考生软件缺点 编辑:程序博客网 时间:2024/05/19 09:47

本文转载自:http://blog.csdn.net/zhoutao198712/article/details/20864143


在Github上看到一些进度条的功能,都是通过Core Graph来实现。无所谓正确与否,但是开发效率明显就差很多了,而且运行效率还是值得考究的。其实使用苹果提供的Core Animation能够非常简单和方便的实现环形进度条效果,而且还可以高效的保证动画效果,无论是前进还是后退(语言水平比较有限,就多用代码说话)。

1、先来一个结果

80%的状态:


99%的状态:


2、需要用到的宏:

[objc] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #define degreesToRadians(x) (M_PI*(x)/180.0) //把角度转换成PI的方式  
  2. #define  PROGREESS_WIDTH 80 //圆直径   
  3. #define PROGRESS_LINE_WIDTH 4 //弧线的宽度  

3、CAShapeLayer

   首先,你得要引入Core Animation框架。为了实现环形效果,需要使用到CAShapeLayer,原理是CAShapeLayer可以通过指定Path的方式实现生成一个图形,非常方便。


4、UIBezierPath

    由于需要画一个圆形,UIBeziperPath是非常好用的画圆形的工具。实现下面的代码可以画出上面所示的整个轨道。这个圆形是从-210度的角度到30度。

[objc] view plaincopy在CODE上查看代码片派生到我的代码片
  1. UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(4040) radius:(PROGREESS_WIDTH-PROGRESS_LINE_WIDTH)/2 startAngle:degreesToRadians(-210) endAngle:degreesToRadians(30) clockwise:YES];  

5、画出一个完成的进度的背景轨道

这里原理很简单,就是使用CAShapeLayer和UIBezierPath结合起来就能够达成目标,这一步的结果如下所示:

[objc] view plaincopy在CODE上查看代码片派生到我的代码片
  1. _trackLayer = [CAShapeLayer layer];//创建一个track shape layer  
  2. _trackLayer.frame = self.bounds;  
  3. [self.layer addSublayer:_trackLayer];  
  4. _trackLayer.fillColor = [[UIColor clearColor] CGColor];  
  5.  _trackLayer.strokeColor = [_strokeColor CGColor];//指定path的渲染颜色  
  6. _trackLayer.opacity = 0.25//背景同学你就甘心做背景吧,不要太明显了,透明度小一点  
  7. _trackLayer.lineCap = kCALineCapRound;//指定线的边缘是圆的  
  8. _trackLayer.lineWidth = PROGRESS_LINE_WIDTH;//线的宽度  
  9. UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(4040) radius:(PROGREESS_WIDTH-PROGRESS_LINE_WIDTH)/2 startAngle:degreesToRadians(-210) endAngle:degreesToRadians(30) clockwise:YES];//上面说明过了用来构建圆形  
  10. _trackLayer.path =[path CGPath]; //把path传递給layer,然后layer会处理相应的渲染,整个逻辑和CoreGraph是一致的。  


6、渐变进度条:

首先要明确的需求是,我们需要颜色根据百分比从红色渐变到黄色然后再到蓝色。
怎么实现这个颜色的渐变效果。这里我们需要使用到CAGradientLayer,CAGradientLayer是一个用来画颜色渐变的层(如果使用透明的颜色,也就可以做到透明渐变)。我们先用CAGradientLayer做出渐变效果,然后把ShapeLayer作为GradientLayer的Mask来截取出需要的部分,以此达到渐变的进度条效果。

    首先,需要构建出顺着弧形的颜色渐变。上面的需求我们可以分解成两部分。
    ①左半部分,颜色从红色渐变到黄色。
    ②右半部分,颜色从黄色渐变到蓝色。
    由此可以了解到是我们需要两个CAShapeLayer。
    为什么要这么折腾?CAShapeLayer不能顺着弧线进行渐变只能指定两个点之间进行渐变。所以只能曲线救国了。
    先看看这个部分的效果:

    

    然后,创建一个新的CAShapeLayer来截取这个颜色渐变的层。
    这部分代码如下所示:

    

[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. _progressLayer = [CAShapeLayer layer];  
  2. _progressLayer.frame = self.bounds;  
  3. _progressLayer.fillColor =  [[UIColor clearColor] CGColor];  
  4. _progressLayer.strokeColor  = [PROCESS_COLOR CGColor];  
  5. _progressLayer.lineCap = kCALineCapRound;  
  6. _progressLayer.lineWidth = PROGRESS_LINE_WIDTH;  
  7. _progressLayer.path = [path CGPath];  
  8. _progressLayer.strokeEnd = 0;  
  9.   
  10. CALayer *gradientLayer = [CALayer layer];  
  11. CAGradientLayer *gradientLayer1 =  [CAGradientLayer layer];  
  12. gradientLayer1.frame = CGRectMake(0, 0, self.width/2, self.height);  
  13. [gradientLayer1 setColors:[NSArray arrayWithObjects:(id)[[UIColor redColor] CGColor],(id)[UIColorFromRGB(0xfde802) CGColor], nil]];  
  14. [gradientLayer1 setLocations:@[@0.5,@0.9,@1 ]];  
  15. [gradientLayer1 setStartPoint:CGPointMake(0.5, 1)];  
  16. [gradientLayer1 setEndPoint:CGPointMake(0.5, 0)];  
  17. [gradientLayer addSublayer:gradientLayer1];  
  18.   
  19. CAGradientLayer *gradientLayer2 =  [CAGradientLayer layer];  
  20. [gradientLayer2 setLocations:@[@0.1,@0.5,@1]];  
  21. gradientLayer2.frame = CGRectMake(self.width/2, 0, self.width/2, self.height);  
  22. [gradientLayer2 setColors:[NSArray arrayWithObjects:(id)[UIColorFromRGB(0xfde802) CGColor],(id)[MAIN_BLUE CGColor], nil]];  
  23. [gradientLayer2 setStartPoint:CGPointMake(0.5, 0)];  
  24. [gradientLayer2 setEndPoint:CGPointMake(0.5, 1)];  
  25. [gradientLayer addSublayer:gradientLayer2];  
  26.   
  27.   
  28.   
  29. [gradientLayer setMask:_progressLayer]; //用progressLayer来截取渐变层  
  30. [self.layer addSublayer:gradientLayer];  

7、进度条效果

        走到上面一步我们得到的效果是一个进度为100%的效果,_progressLayer的长度和_trackLayer的长度是一样的。那么怎么解决百分比的问题呢?

        CAShapeLayer有一个strokeEnd的属性,这个属性是从0到1的浮点类型,正好可以用表达百分比,而且这个属性是animatable,可以动态的表示进度的变化。
如下代码所示:

[objc] view plaincopy在CODE上查看代码片派生到我的代码片
  1. -(void)setPercent:(NSInteger)percent animated:(BOOL)animated  
  2. {  
  3.     [CATransaction begin];  
  4.     [CATransaction setDisableActions:!animated];  
  5.     [CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]];  
  6.     [CATransaction setAnimationDuration:MAIN_SCREEN_ANIMATION_TIME];  
  7.     _progressLayer.strokeEnd = percent/100.0;  
  8.     [CATransaction commit];  
  9.       
  10.     _percent = percent;  
  11. }  


8、总结

①进度条的百分比是通过CAShapeLayer的strokeEnd属性来实现。
②环形的渐变进度条,通过结合CAShapeLayer和CAGradientLayer实现,注意layer的mask属性的使用。


原文链接:http://www.ganlvji.com/gradient_circle_progress/


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 华为麦芒5网络差怎么办 华为麦芒无线信号不好怎么办 华为麦芒6网络不好怎么办 华为麦芒6信号差怎么办 华为手机无线网信号差怎么办 华为麦芒6数据信号差怎么办 华为麦芒54g信号差怎么办 华为手机wifi信号差怎么办 华为手机导航信号弱怎么办 华为手机gps信号弱怎么办 麦芒5指纹消失了怎么办 华为应用锁密码忘了怎么办 华为麦芒5密码忘了怎么办 华为卡1无服务怎么办 经常卡1无服务怎么办 华为手机进水无服务怎么办 苹果手机进水后无服务怎么办 苹果6进水无服务怎么办 华为手机突然无服务怎么办 sim卡显示无服务怎么办 华为麦芒进水无限开关机怎么办 华为麦芒5进水黑屏怎么办 华为麦芒6进水了怎么办 4g手机开不开机怎么办 全屏钢化膜总是翘边怎么办 华为麦芒屏幕触屏失灵怎么办 华为麦芒5运行慢怎么办 手机屏保密码忘记了怎么办 麦芒5密码锁忘了怎么办 超薄手机壳松了怎么办 华为麦芒5声音小怎么办 笔记本外壳a面裂了怎么办 苹果手机外壳摔坏了怎么办 挂衣服肩膀出包怎么办 摩拜单车手机号注销了怎么办 摩拜单车手机号码换了怎么办 摩拜单车换手机号码打不开怎么办 摩拜单车丢了怎么办 摩拜单车忘锁了怎么办 透明手机壳粘指纹怎么办 tpu手机壳变黄了怎么办