您的位置:首页 > 产品设计 > UI/UE

CAGradientLayer,CAShapeLayer及UIBezierPath实现环形彩色进度条

2016-01-06 18:20 183 查看
结合CAGradientLayer,CAShapeLayer及UIBezierPath实现环形彩色进度条



CAGradientLayer: 渐变色

CAShapeLayer: 提供显示图层渲染需要结合UIBezierPath

UIBezierPath: 提供路径

CAShapeLayer:

1, CAShapeLayer继承自CALayer,可使用CALayer的所有属性

2, CAShapeLayer需要和贝塞尔曲线配合使用才有意义。

Shape:形状

贝塞尔曲线可以为其提供形状,而单独使用CAShapeLayer是没有任何意义的。

3, 使用CAShapeLayer与贝塞尔曲线可以实现不在view的DrawRect方法中画出一些想要的图形

关于CAShapeLayer和DrawRect的比较

DrawRect:DrawRect属于CoreGraphic框架,占用CPU,消耗性能大

CAShapeLayer:CAShapeLayer属于CoreAnimation框架,通过GPU来渲染图形,节省性能。动画渲染直接提交给手机GPU,不消耗内存

贝塞尔曲线与CAShapeLayer的关系

1,CAShapeLayer中shape代表形状的意思,所以需要形状才能生效

2,贝塞尔曲线可以创建基于矢量的路径

3,贝塞尔曲线给CAShapeLayer提供路径,CAShapeLayer在提供的路径中进行渲染。路径会闭环,所以绘制出了Shape

4,用于CAShapeLayer的贝塞尔曲线作为Path,其path是一个首尾相接的闭环的曲线,即使该贝塞尔曲线不是一个闭环的曲线

创建 渐变色的进度条之前先了解一下CAGradientLayer 和 CAShapeLayer的基本用法, 至于UIBezierPath则在前面的文章中有详细的说明

CAGradientLayer

CAGradientLayer是单位坐标系

1,CAGradientLayer的坐标系统是从(0,0)到(1,1)绘制的矩形

2,CAGradientLayer的frame值的size不为正方形的话,坐标系统会被拉伸

3,CAGradientLayer的startPoint和endPoint会直接决定颜色的绘制方向

4,CAGradientLayer的颜色分割点时以0到1的比例来计算的

@implementation ViewController

- (void)viewDidLoad {
[super viewDidLoad];

//初始化imageView
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"2.jpg"]];
imageView.frame = CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height);
imageView.center = self.view.center;
[self.view addSubview:imageView];

//初始化渐变层
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
//设置渐变层的 rect
gradientLayer.frame = imageView.bounds;
[imageView.layer addSublayer:gradientLayer];

//设置渐变颜色方向, startPoint和endPoint会直接决定颜色的绘制方向
gradientLayer.startPoint = CGPointMake(0, 0);
gradientLayer.endPoint = CGPointMake(0, 1);

//设定颜色组
gradientLayer.colors = @[(id)[UIColor clearColor].CGColor,
(id)[UIColor colorWithRed:0.000 green:1.000 blue:0.502 alpha:1.000].CGColor,
(id)[UIColor purpleColor].CGColor,
(id)[UIColor blueColor].CGColor];

//设定颜色分割点
gradientLayer.locations = @[@(0.2f) , @(0.6f) , @(0.7f) , @(0.9f) ];

}


CAShapeLayer: 提供显示图层渲染需要结合UIBezierPath

//创建出CAShapeLayer
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
//设置shapeLayer的尺寸和位置
shapeLayer.frame = CGRectMake(0, 0, 200, 200);
//设置中心position
shapeLayer.position = self.view.center;
//填充颜色为ClearColor
shapeLayer.fillColor = [UIColor clearColor].CGColor;

//设置线条的宽度和颜色
shapeLayer.lineWidth = 1.0f;
shapeLayer.strokeColor = [UIColor redColor].CGColor;

//填充色
shapeLayer.fillColor = [UIColor clearColor].CGColor;
//线 颜色
shapeLayer.strokeColor = [UIColor redColor].CGColor;

//创建出圆形贝塞尔曲线
UIBezierPath *circlePath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, 200, 200)];

//让贝塞尔曲线与CAShapeLayer产生联系
shapeLayer.path = circlePath.CGPath;

//添加并显示
[self.view.layer addSublayer:shapeLayer]


//设置stroke起始点
shapeLayer.strokeStart = 0.5;
shapeLayer.strokeEnd = 0.85;


好吧, 暂时就这么多吧

开始实现 进度条

#import "ZHZProgressView.h"

#define VRadians(x) (M_PI*(x)/180.0) //把角度转换成PI的方式
#define kLineW 8 //弧线的宽度

#define kViewW self.frame.size.width
#define kViewH self.frame.size.height

@interface ZHZProgressView () {
UILabel *label;
}

@property (nonatomic, strong)CAShapeLayer *shapeLayer;

@end

@implementation ZHZProgressView

- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
CGFloat labelW = self.frame.size.width - kLineW * 2;
CGFloat labelH = self.frame.size.height - kLineW * 2;

label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, labelW, labelH)];
label.center = self.center;
label.backgroundColor = [UIColor clearColor];
label.textColor = [UIColor blueColor];
label.font = [UIFont systemFontOfSize:20];
label.textAlignment = NSTextAlignmentCenter;
[self addSubview:label];
}
return self;
}

- (void)drawRect:(CGRect)rect {

//设置路径
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.frame.size.width / 2.0, self.frame.size.height / 2.0) radius:self.frame.size.width / 2.0 - kLineW startAngle:VRadians(-210) endAngle:VRadians(30) clockwise:YES];
path.lineWidth = kLineW;
path.lineJoinStyle = kCGLineJoinRound;
path.lineCapStyle = kCGLineCapRound;
[[UIColor colorWithWhite:0.667 alpha:0.343] set];
[path stroke];

self.shapeLayer = [CAShapeLayer layer];
self.shapeLayer.frame = self.bounds;

self.shapeLayer.fillColor = [UIColor clearColor].CGColor;
self.shapeLayer.strokeColor = [UIColor redColor].CGColor;

self.shapeLayer.lineJoin = kCALineCapRound;
self.shapeLayer.lineCap = kCALineCapRound;
self.shapeLayer.lineWidth = kLineW;
self.shapeLayer.path = path.CGPath;

CALayer *gradientLayer = [CALayer layer];
CAGradientLayer *gradientLayer1 =  [CAGradientLayer layer];
gradientLayer1.frame = CGRectMake(0, 0, self.frame.size.width/2, self.frame.size.height);
gradientLayer1.colors = @[
(id)[UIColor redColor].CGColor,
(id)[UIColor greenColor].CGColor,
];

[gradientLayer1 setStartPoint:CGPointMake(0.5, 1)];
[gradientLayer1 setEndPoint:CGPointMake(0.5, 0)];
[gradientLayer addSublayer:gradientLayer1];

CAGradientLayer *gradientLayer2 =  [CAGradientLayer layer];
gradientLayer2.frame = CGRectMake(self.frame.size.width/2, 0, self.frame.size.width/2, self.frame.size.height);
gradientLayer2.colors = @[
(id)[UIColor greenColor].CGColor,
(id)[UIColor redColor].CGColor
];
[gradientLayer2 setStartPoint:CGPointMake(0.5, 0)];
[gradientLayer2 setEndPoint:CGPointMake(0.5, 1)];
[gradientLayer addSublayer:gradientLayer2];
[self.layer addSublayer:gradientLayer];

gradientLayer.mask = self.shapeLayer;

self.shapeLayer.strokeEnd = 0;

}

- (void)setPercent:(NSInteger)percent animated:(BOOL)animated {
[CATransaction begin];
[CATransaction setDisableActions:!animated];
[CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]];
[CATransaction setAnimationDuration:0.1];
self.shapeLayer.strokeEnd = percent/100.0;
[CATransaction commit];

self.percent = percent;
}

- (void)setPercent:(NSInteger)percent {

NSString *progress = [NSString stringWithFormat:@"%ld%%", percent];
label.text = progress;
}

@end


参考:1. https://www.ganlvji.com/gradient_circle_progress/

2. /article/1217323.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: