CAShapeLayer 与贝塞尔曲线

一 CAShapeLayer 简介

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

2,CAShapeLayer需要与贝塞尔曲线配合使用才有意义;单独使用毫无意义

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

4,CAShapeLayer属于Core  Animation框架,其动画渲染直接提交到手机的GPU当中,相较于view的drawRect方法使用CPU渲染而言,其效率极高,

能大大优化内存使用情况。

drawRect 属于Core Graphics 框架,走CPU,耗性能较大。

5,示例:

@interface SubLayerVC ()

@property (nonatomic, strong) NSTimer      *timer;
@property (nonatomic, strong) CAShapeLayer *shapeLayer; @end @implementation SubLayerVC - (void)viewDidLoad {
[super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor];
// 创建shapeLayer
_shapeLayer = [CAShapeLayer layer];
_shapeLayer.frame = (CGRect){CGPointMake(, ), CGSizeMake(, )};
_shapeLayer.position = self.view.center;
_shapeLayer.path = [self getStar1BezierPath].CGPath;
_shapeLayer.fillColor = [UIColor clearColor].CGColor;
_shapeLayer.strokeColor = [UIColor redColor].CGColor;
_shapeLayer.lineWidth = .f;
[self.view.layer addSublayer:_shapeLayer]; // 创建定时器
_timer = [NSTimer scheduledTimerWithTimeInterval:.f
target:self
selector:@selector(pathAnimation)
userInfo:nil
repeats:YES]; } /**
* 执行path的动画
*/
- (void)pathAnimation {
static int i = ;
if (i++ % == ) {
CABasicAnimation *circleAnim = [CABasicAnimation animationWithKeyPath:@"path"];
circleAnim.removedOnCompletion = NO;
circleAnim.duration = ;
circleAnim.fromValue = (__bridge id)[self getStar1BezierPath].CGPath;
circleAnim.toValue = (__bridge id)[self getStar2BezierPath].CGPath;
_shapeLayer.path = [self getStar2BezierPath].CGPath;
[_shapeLayer addAnimation:circleAnim forKey:@"animateCirclePath"];
} else {
CABasicAnimation *circleAnim = [CABasicAnimation animationWithKeyPath:@"path"];
circleAnim.removedOnCompletion = NO;
circleAnim.duration = ;
circleAnim.fromValue = (__bridge id)[self getStar2BezierPath].CGPath;
circleAnim.toValue = (__bridge id)[self getStar1BezierPath].CGPath;
_shapeLayer.path = [self getStar1BezierPath].CGPath;
[_shapeLayer addAnimation:circleAnim forKey:@"animateCirclePath"];
}
} /**
* 贝塞尔曲线1
*
* @return 贝塞尔曲线
*/
-(UIBezierPath *)getStar1BezierPath {
//// Star Drawing
UIBezierPath* starPath = [UIBezierPath bezierPath];
[starPath moveToPoint: 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)];
[starPath closePath]; return starPath;
}
/**
* 贝塞尔曲线2
*
* @return 贝塞尔曲线
*/
-(UIBezierPath *)getStar2BezierPath {
//// Star Drawing
UIBezierPath* starPath = [UIBezierPath bezierPath];
[starPath moveToPoint: 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)];
[starPath closePath]; return starPath;
}
CAShapeLayer 与贝塞尔曲线

二贝赛尔曲线与CAShapeLayer的关系

1,CAShapeLayer,含shape,顾名思义,它需要一个形状才能生效;

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

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

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

shape.masksToBounds = YES ; //禁止内容显示超出CAShapeLayer的frame值。

贝塞尔曲线的frame值与CAShapeLayer的frame值互不干扰,CAShaperLayer的frame值不能小于贝塞尔曲线的frame值。

CAShapeLayer 与贝塞尔曲线

三 CAShapeLayer 之 strokeStart与strokeEnd动画

1,将shapeLayer的fillColor设置为透明背景

2,设置线条的宽度(lineWidth)的值

3,设置线条的颜色

4,将strokeStart值设定为0,然后让stokeEnd的值变化触发隐式动画

   - (void)viewDidLoad {
[super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor];
// 创建椭圆形贝塞尔曲线
UIBezierPath *oval = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(, , , )]; // 创建CAShapeLayer
_shapeLayer3 = [CAShapeLayer layer];
_shapeLayer3.frame = CGRectMake(, , , );
_shapeLayer3.position = self.view.center; // 修改CAShapeLayer的线条相关值
_shapeLayer3.fillColor = [UIColor clearColor].CGColor;
_shapeLayer3.strokeColor = [UIColor redColor].CGColor;
_shapeLayer3.lineWidth = .f; //0 是最右侧点,0.25是最下方的点,0.5是最左侧的点,0.75是最顶端的点
_shapeLayer3.strokeStart = .f;
_shapeLayer3.strokeEnd = .f; // 建立贝塞尔曲线与CAShapeLayer之间的关联
_shapeLayer3.path = oval.CGPath; // 添加并显示
[self.view.layer addSublayer:_shapeLayer3]; // 创建定时器
_timer = [NSTimer scheduledTimerWithTimeInterval:.f
target:self
selector:@selector(animationEventTypeTwo)
userInfo:nil
repeats:YES]; } /**
* 动画效果1
*/
- (void)animationEventTypeOne {
// 执行隐式动画
_shapeLayer3.strokeEnd = arc4random() % / .f;
} /**
* 动画效果2
*/
- (void)animationEventTypeTwo {
CGFloat valueOne = arc4random() % / .f;
CGFloat valueTwo = arc4random() % / .f; // 执行隐式动画
_shapeLayer3.strokeStart = valueOne < valueTwo ? valueOne : valueTwo;
_shapeLayer3.strokeEnd = valueOne > valueTwo ? valueOne : valueTwo;
}

四   贝塞尔曲线 其他方法:

1,根据一个矩形画曲线

+ (UIBezierPath *)bezierPathWithRect:(CGRect)rect

2,根据矩形框的内切圆画曲线

+ (UIBezierPath *)bezierPathWithOvalInRect:(CGRect)rect

3,

//以某个中心点画弧线
+ (UIBezierPath *)bezierPathWithArcCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise;

参数:

center:弧线中心点的坐标

radius:弧线所在圆的半径

startAngle:弧线开始的角度值

endAngle:弧线结束的角度值

clockwise:是否顺时针画弧线

4,

//画二元曲线,一般和moveToPoint配合使用

- (void)addQuadCurveToPoint:(CGPoint)endPoint controlPoint:(CGPoint)controlPoint

参数:

endPoint:曲线的终点

controlPoint:画曲线的基准点

//以三个点画一段曲线,一般和moveToPoint配合使用

- (void)addCurveToPoint:(CGPoint)endPoint controlPoint1:(CGPoint)controlPoint1 controlPoint2:(CGPoint)controlPoint2

参数:

endPoint:曲线的终点

controlPoint1:画曲线的第一个基准点

controlPoint2:画曲线的第二个基准点

上一篇:oracle 存储过程 示例


下一篇:Android基本控件之ListView(一)