一、CAShapeLayer简单介绍:
1、CAShapeLayer继承至CALayer,能够使用CALayer的全部属性值
2、CAShapeLayer须要与贝塞尔曲线配合使用才有意义
3、使用CAShapeLayer与贝塞尔曲线能够实现不在view的drawRect方法中画出一些想要的图形
4、CAShapeLayer属于CoreAnimation框架,其动画渲染直接提交到手机的GPU其中,相较于view的drawRect方法使用CPU渲染而言,其效率极高,能大大优化内存使用情况
五角星动画
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic,strong) NSTimer *timer;
@property (nonatomic,strong) CAShapeLayer *shapeLayer;
@end
@implementation ViewController
- (void)viewDidLoad {
[superviewDidLoad];
// 创建shapeLayer
_shapeLayer = [CAShapeLayerlayer];
_shapeLayer.frame = (CGRect){CGPointMake(0,0), CGSizeMake(200,200)};
_shapeLayer.position =self.view.center;
_shapeLayer.path = [selfgetStar1BezierPath].CGPath;
_shapeLayer.fillColor = [UIColorclearColor].CGColor;
_shapeLayer.strokeColor = [UIColorredColor].CGColor;
_shapeLayer.lineWidth =2.f;
[self.view.layeraddSublayer:_shapeLayer];
// 创建定时器
_timer = [NSTimerscheduledTimerWithTimeInterval:1.f
target:self
selector:@selector(pathAnimation)
userInfo:nil
repeats:YES];
}
/**
* 运行path的动画
*/
- (void)pathAnimation {
static int i =0;
if (i++ % 2 ==0) {
CABasicAnimation *circleAnim = [CABasicAnimationanimationWithKeyPath:@"path"];
circleAnim.removedOnCompletion =NO;
circleAnim.duration =1;
circleAnim.fromValue = (__bridgeid)[self getStar1BezierPath].CGPath;
circleAnim.toValue = (__bridgeid)[self getStar2BezierPath].CGPath;
_shapeLayer.path = [selfgetStar2BezierPath].CGPath;
[_shapeLayeraddAnimation:circleAnim forKey:@"animateCirclePath"];
}else {
CABasicAnimation *circleAnim = [CABasicAnimationanimationWithKeyPath:@"path"];
circleAnim.removedOnCompletion =NO;
circleAnim.duration =1;
circleAnim.fromValue = (__bridgeid)[self getStar2BezierPath].CGPath;
circleAnim.toValue = (__bridgeid)[self getStar1BezierPath].CGPath;
_shapeLayer.path = [selfgetStar1BezierPath].CGPath;
[_shapeLayeraddAnimation:circleAnim forKey:@"animateCirclePath"];
}
}
/**
* 贝塞尔曲线1
*
* @return 贝塞尔曲线
*/
-(UIBezierPath *)getStar1BezierPath {
//// Star Drawing
UIBezierPath* starPath = [UIBezierPathbezierPath];
[starPathmoveToPoint: CGPointMake(22.5,2.5)];
[starPath addLineToPoint:CGPointMake(28.32,14.49)];
[starPath addLineToPoint:CGPointMake(41.52,16.32)];
[starPath addLineToPoint:CGPointMake(31.92,25.56)];
[starPath addLineToPoint:CGPointMake(34.26,38.68)];
[starPath addLineToPoint:CGPointMake(22.5,32.4)];
[starPath addLineToPoint:CGPointMake(10.74,38.68)];
[starPath addLineToPoint:CGPointMake(13.08,25.56)];
[starPath addLineToPoint:CGPointMake(3.48,16.32)];
[starPath addLineToPoint:CGPointMake(16.68,14.49)];
[starPathclosePath];
return starPath;
}
/**
* 贝塞尔曲线2
*
* @return 贝塞尔曲线
*/
-(UIBezierPath *)getStar2BezierPath {
//// Star Drawing
UIBezierPath* starPath = [UIBezierPathbezierPath];
[starPathmoveToPoint: CGPointMake(22.5,2.5)];
[starPath addLineToPoint:CGPointMake(32.15,9.21)];
[starPath addLineToPoint:CGPointMake(41.52,16.32)];
[starPath addLineToPoint:CGPointMake(38.12,27.57)];
[starPath addLineToPoint:CGPointMake(34.26,38.68)];
[starPath addLineToPoint:CGPointMake(22.5,38.92)];
[starPath addLineToPoint:CGPointMake(10.74,38.68)];
[starPath addLineToPoint:CGPointMake(6.88,27.57)];
[starPath addLineToPoint:CGPointMake(3.48,16.32)];
[starPath addLineToPoint:CGPointMake(12.85,9.21)];
[starPathclosePath];
return starPath;
}
@end
二、贝塞尔曲线与CAShapeLayer的关系
1、CAShapeLayer中有Shape这个单词。顾名思义,它须要一个形状才干生效
2、贝塞尔曲线能够创建基于矢量的路径
3、贝塞尔曲线给CAShapeLayer提供路径。CAShapeLayer在提供的路径中进行渲染。路径会闭环,所以路径绘制出了Shape
4、用于CAShapeLayer的贝塞尔曲线作为path,其path是一个首尾相接的闭环的曲线,即使该贝塞尔曲线不是一个闭环的曲线
注意:shape的frame 要大于BezierPath的frame.BezierPath不会由于share的frame而拉升。否则BezierPath截断
- (void)viewDidLoad {
[superviewDidLoad];
//创建椭圆形贝塞尔曲线
UIBezierPath *oval = [UIBezierPathbezierPathWithOvalInRect:CGRectMake(0,0, 200,100)];
//创建矩形贝塞尔曲线
UIBezierPath *rect = [UIBezierPathbezierPathWithRect:CGRectMake(0,0, 200,100)];
//创建圆形贝塞尔曲线
UIBezierPath *circle = [UIBezierPathbezierPathWithOvalInRect:CGRectMake(0,0, 100,100)];
// 创建CAShapeLayer
CAShapeLayer *shape = [CAShapeLayerlayer];
shape.frame =CGRectMake(0,0, 200, 50);
shape.position =self.view.center;
// 显示CAShapeLayer的边界
shape.borderWidth =1.f;
// 禁止内容显示超出CAShapeLayer的frame值
shape.masksToBounds =YES;
//改动贝塞尔曲线的填充颜色
shape.fillColor = [UIColorredColor].CGColor;
// 建立贝塞尔曲线与CAShapeLayer之间的关联
shape.path = circle.CGPath;
// 加入并显示
[self.view.layeraddSublayer:shape];
}
三、StrokeStart与StrokeEnd动画
1、将ShapeLayer的fillColor设置成透明背景
2、设置线条的宽度(lineWidth)的值
3、设置线条的颜色
4、将strokeStart值设定成0,然后让strokeEnd的值变化触发隐式动画
@interface ViewController ()
@property (nonatomic,strong) NSTimer *timer; // 定时器
@property (nonatomic,strong) CAShapeLayer *shapeLayer;// 形状layer
@end
@implementation ViewController
- (void)viewDidLoad {
[superviewDidLoad];
// 设置背景色
self.view.backgroundColor = [UIColorcolorWithRed:0.878green:0.878blue:0.878alpha:1];
//创建椭圆形贝塞尔曲线
UIBezierPath *oval = [UIBezierPathbezierPathWithOvalInRect:CGRectMake(0,0, 100,100)];
// 创建CAShapeLayer
_shapeLayer = [CAShapeLayerlayer];
_shapeLayer.frame =CGRectMake(0,0, 100, 100);
_shapeLayer.position =self.view.center;
// 改动CAShapeLayer的线条相关值
_shapeLayer.fillColor = [UIColorclearColor].CGColor;
_shapeLayer.strokeColor = [UIColorredColor].CGColor;
_shapeLayer.lineWidth =2.f;
_shapeLayer.strokeStart =0.f;
_shapeLayer.strokeEnd =0.f;
// 建立贝塞尔曲线与CAShapeLayer之间的关联
_shapeLayer.path = oval.CGPath;
// 加入并显示
[self.view.layeraddSublayer:_shapeLayer];
// 创建定时器
_timer = [NSTimerscheduledTimerWithTimeInterval:1.f
target:self
selector:@selector(animationEventTypeTwo)
userInfo:nil
repeats:YES];
}
/**
* 动画效果1
*/
- (void)animationEventTypeOne {
// 运行隐式动画
_shapeLayer.strokeEnd =arc4random() % 100 /100.f;
}
/**
* 动画效果2
*/
- (void)animationEventTypeTwo {
CGFloat valueOne = arc4random() % 100 / 100.f;
CGFloat valueTwo = arc4random() % 100 / 100.f;
// storkeStar 与storkeEnd同一时候赋值。strokeStart要小于strokeEnd的值
// 运行隐式动画
_shapeLayer.strokeStart = valueOne < valueTwo ?
valueOne : valueTwo;
_shapeLayer.strokeEnd = valueOne > valueTwo ?
valueOne : valueTwo;
}
@end
四、用CAShapeLayer实现圆形进度条效果
1、确定须要设定的參数
2、实现细节
3、进行測试
@interface CircleView :UIView
@property (nonatomic,assign) CGFloat startValue;// 起始值(0~1)
@property (nonatomic,assign) CGFloat lineWidth; // 线宽(>0)
@property (nonatomic,strong) UIColor *lineColor; // 线条颜色
@property (nonatomic,assign) CGFloat value; // 变化的值
@end
#import "CircleView.h"
@interface CircleView ()
@property (nonatomic,strong) CAShapeLayer *shapeLayer;
@end
@implementation CircleView
- (instancetype)initWithFrame:(CGRect)frame {
self = [superinitWithFrame:frame];
if (self) {
// 创建出CAShapeLayer
_shapeLayer = [CAShapeLayerlayer];
_shapeLayer.frame =self.bounds;
// 创建出贝塞尔曲线
UIBezierPath *path = [UIBezierPathbezierPathWithOvalInRect:self.bounds];
// 贝塞尔曲线与CAShapeLayer产生关联
_shapeLayer.path = path.CGPath;
// 基本配置
_shapeLayer.fillColor = [UIColorclearColor].CGColor;
_shapeLayer.lineWidth =1.f;
_shapeLayer.strokeColor = [UIColorredColor].CGColor;
_shapeLayer.strokeEnd =0.f;
// 加入到当前view
[self.layeraddSublayer:_shapeLayer];
}
return self;
}
@synthesize startValue =_startValue;
- (void)setStartValue:(CGFloat)startValue {
_startValue = startValue;
_shapeLayer.strokeEnd = startValue;
}
- (CGFloat)startValue {
return_startValue;
}
@synthesize lineWidth =_lineWidth;
- (void)setLineWidth:(CGFloat)lineWidth {
_lineWidth = lineWidth;
_shapeLayer.lineWidth = lineWidth;
}
- (CGFloat)lineWidth {
return_lineWidth;
}
@synthesize lineColor =_lineColor;
- (void)setLineColor:(UIColor *)lineColor {
_lineColor = lineColor;
_shapeLayer.strokeColor = lineColor.CGColor;
}
- (UIColor *)lineColor {
return_lineColor;
}
@synthesize value = _value;
- (void)setValue:(CGFloat)value {
_value = value;
_shapeLayer.strokeEnd = value;
}
- (CGFloat)value {
return _value;
}
@end
#import "CircleView.h"
@interface ViewController ()
{
CircleView *circle;
}
@end
@implementation ViewController
- (void)viewDidLoad {
[superviewDidLoad];
circle = [[CircleViewalloc] initWithFrame:CGRectMake(0,0, 200, 200)];
circle.center =self.view.center;
circle.startValue =0.5;
circle.lineWidth =3.f;
circle.lineColor = [UIColorgrayColor];
[self.viewaddSubview:circle];
[selfperformSelector:@selector(delayAnimation)
withObject:nil
afterDelay:3.f];
}
- (void)delayAnimation {
circle.value =1.f;
}
@end