之前一直对CAShapeLayer和UIBezierPath不太了解,后来发现在iOS里面有很多动画效果都是通过这两个东西弄的,所以就抽时间来了解一下.
CAShapeLayer继承自CALayer,可使用CALayer的所有属性,但是比 CALayer 更灵活,可以画出各种图形.CAShapeLayer 有一个神奇的属性 path 用这个属性配合上 UIBezierPath 这个类就可以达到意想不到的效果.
使用UIBezierPath可以创建基于矢量的路径,此类是Core Graphics框架关于路径的封装(本质是UIBezierPath是对CGPathRef类型的封装)。使用此类可以定义简单的形状,如椭圆、矩形或者有多个直线和曲线段组成的形状等。
CAShapeLayer与UIBezierPath的关系:
CAShapeLayer中shape代表形状的意思,所以需要形状才能生效,贝塞尔曲线可以为其提供形状,而单独使用CAShapeLayer是没有任何意义的.贝塞尔曲线可以创建基于矢量的路径,而UIBezierPath类是对CGPathRef的封装.
贝塞尔曲线给CAShapeLayer提供路径,CAShapeLayer在提供的路径中进行渲染。路径会闭环,所以绘制出了Shape.用于CAShapeLayer的贝塞尔曲线作为path,其path是一个首尾相接的闭环的曲线,即使该贝塞尔曲线不是一个闭环的曲线.
关于CAShapeLayer和DrawRect的比较
- DrawRect:DrawRect属于CoreGraphic框架,占用CPU,消耗性能大
- CAShapeLayer:CAShapeLayer属于CoreAnimation框架,通过GPU来渲染图形,节省性能。动画渲染直接提交给手机GPU,不消耗内存
一、常用方法
+ (instancetype)bezierPath;
这个使用比较多,因为这个工厂方法创建的对象,我们可以根据我们的需要任意定制样式,可以画任何我们想画的图形。
+ (instancetype)bezierPathWithRect:(CGRect)rect;
这个工厂方法根据一个矩形画贝塞尔曲线。
+ (instancetype)bezierPathWithOvalInRect:(CGRect)rect;
这个工厂方法根据一个矩形画内切曲线。通常用它来画圆或者椭圆。
+ (instancetype)bezierPathWithRoundedRect:(CGRect)rect cornerRadius:(CGFloat)cornerRadius;
+ (instancetype)bezierPathWithRoundedRect:(CGRect)rect byRoundingCorners:(UIRectCorner)corners cornerRadii:(CGSize)cornerRadii;
第一个工厂方法是画矩形,但是这个矩形是可以画圆角的。第一个参数是矩形,第二个参数是圆角大小。
第二个工厂方法功能是一样的,但是可以指定某一个角画成圆角。像这种我们就可以很容易地给UIView扩展添加圆角的方法了。
+ (instancetype)bezierPathWithArcCenter:(CGPoint)center
radius:(CGFloat)radius
startAngle:(CGFloat)startAngle
endAngle:(CGFloat)endAngle
clockwise:(BOOL)clockwise;
这个工厂方法用于画弧,参数说明如下:
center: 弧线中心点的坐标
radius: 弧线所在圆的半径
startAngle: 弧线开始的角度值
endAngle: 弧线结束的角度值
clockwise: 是否顺时针画弧线
- (void)closePath;//闭合弧线
二、使用示范
//画半圆
CAShapeLayer *shaplayer = [CAShapeLayer layer];
shaplayer.backgroundColor = [UIColor greenColor].CGColor;
//不用非要设置frame,当已经创建了贝塞尔曲线的时候,不需要再次设置frame了
//指定frame,只是为了设置宽度和高度
shaplayer.frame = CGRectMake(0, 0, 300, 300);
// 设置线的颜色
shaplayer.strokeColor = [UIColor orangeColor].CGColor;
// 设置填充颜色
shaplayer.fillColor = [UIColor whiteColor].CGColor;
// 设置居中显示
shaplayer.position = self.view.center;
//线宽度
shaplayer.lineWidth = 10;
//线段出头后的线帽样式
//shaplayer.lineCap = kCALineCapRound;
shaplayer.lineJoin = @"bevel";
// 使用UIBezierPath创建路径
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:self.view.center radius:100 startAngle:M_PI endAngle:M_PI *2 clockwise:YES];
//画圆
//UIBezierPath *circlePath = [UIBezierPath bezierPathWithOvalInRect:frame];
//破折号模式
shaplayer.lineDashPattern = @[@2];
// 设置CAShapeLayer与UIBezierPath关联
shaplayer.path = path.CGPath;
// 将CAShaperLayer放到某个层上显示
[self.view.layer addSublayer:shaplayer];
三、怎么画曲线
CGPoint startPoint = CGPointMake(50, 300);
CGPoint endPoint = CGPointMake(300, 300);
CGPoint controlPoint = CGPointMake(170, 200);
CALayer *layer1 = [CALayer layer];
layer1.frame = CGRectMake(startPoint.x, startPoint.y, 5, 5);
layer1.backgroundColor = [UIColor redColor].CGColor;
CALayer *layer2 = [CALayer layer];
layer2.frame = CGRectMake(endPoint.x, endPoint.y, 5, 5);
layer2.backgroundColor = [UIColor redColor].CGColor;
CALayer *layer3 = [CALayer layer];
layer3.frame = CGRectMake(controlPoint.x, controlPoint.y, 5, 5);
layer3.backgroundColor = [UIColor redColor].CGColor;
UIBezierPath *path = [UIBezierPath bezierPath];
CAShapeLayer *layer = [CAShapeLayer layer];
[path moveToPoint:startPoint];
[path addQuadCurveToPoint:endPoint controlPoint:controlPoint];
layer.path = path.CGPath;
layer.fillColor = [UIColor clearColor].CGColor;
layer.strokeColor = [UIColor blackColor].CGColor;
[self.view.layer addSublayer:layer];
[self.view.layer addSublayer:layer1];
[self.view.layer addSublayer:layer2];
[self.view.layer addSublayer:layer3];
一些特殊的界面效果,也可以通过CAShapeLayer 绘制出来,如下图
//414 600
CGSize finalSize = CGSizeMake(CGRectGetWidth(self.view.frame), 600);
//120
CGFloat layerHeight = finalSize.height * 0.2;
CAShapeLayer *bottomCurveLayer = [[CAShapeLayer alloc]init];
UIBezierPath *pathh = [[UIBezierPath alloc]init];
[pathh moveToPoint:CGPointMake(0, finalSize.height - layerHeight)];//480
[pathh addLineToPoint:CGPointMake(0, finalSize.height - 1)];//599
[pathh addLineToPoint:CGPointMake(finalSize.width, finalSize.height - 1)];//
[pathh addLineToPoint:CGPointMake(finalSize.width, finalSize.height - layerHeight)];
[pathh addQuadCurveToPoint:CGPointMake(0, finalSize.height - layerHeight) controlPoint:CGPointMake(finalSize.width / 2, (finalSize.height - layerHeight) - 40)];
bottomCurveLayer.path = pathh.CGPath;
bottomCurveLayer.fillColor = [UIColor orangeColor].CGColor;
bottomCurveLayer.lineWidth = 5;
[self.view.layer addSublayer:bottomCurveLayer];
还可以用来画虚线
UIView *foot = [[UIView alloc] initWithFrame:CGRectMake(0, 100, 320, 20)];
foot.backgroundColor = [UIColor greenColor];
//layer
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
//设置虚线的颜色 - 颜色请必须设置
[shapeLayer setStrokeColor:[UIColor lightGrayColor].CGColor];
//设置虚线的高度
[shapeLayer setLineWidth:1.0f];
/*
2.f=每条虚线的长度
2.f=每两条线的之间的间距
*/
[shapeLayer setLineDashPattern:
[NSArray arrayWithObjects:[NSNumber numberWithInt:2.f],
[NSNumber numberWithInt:2.f],nil]];
// Setup the path
CGMutablePathRef path1 = CGPathCreateMutable();
/*
代表初始坐标的x,y
y:要和下面的y一样。
*/
CGPathMoveToPoint(path1, NULL,10, 10);
/*
代表坐标的x,y
要与上面的y大小一样,才能使平行的线,不然会画出斜线
*/
CGPathAddLineToPoint(path1, NULL, 320-20,10);
//赋值给shapeLayer
[shapeLayer setPath:path1];
//清除
CGPathRelease(path1);
//可以把self改成任何你想要的UIView.
[[foot layer] addSublayer:shapeLayer];
[self.view addSubview:foot];
还有就是我们的APP中都会用到新手指引界面例如像下面给出的例子也都是用贝塞尔曲线弄出来的效果
self.view.backgroundColor = [UIColor whiteColor];
UIView *v = [[UIView alloc]initWithFrame:CGRectMake(0, 0, SCREENWIDTH, SCREENHEIGHT)];
v.backgroundColor = [[UIColor blackColor]colorWithAlphaComponent:0.3];
[[UIApplication sharedApplication].keyWindow addSubview:v];
//create path 重点来了(**这里需要添加第一个路径)
UIBezierPath *path = [UIBezierPath bezierPathWithRect:[UIScreen mainScreen].bounds];
// 这里添加第二个路径 (这个是圆)
[path appendPath:[UIBezierPath bezierPathWithArcCenter:CGPointMake(30, 60) radius:30 startAngle:0 endAngle:2*M_PI clockwise:NO]];
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.path = path.CGPath;
shapeLayer.strokeColor = [UIColor blackColor].CGColor;
shapeLayer.fillColor = [UIColor blackColor].CGColor;
[v.layer setMask:shapeLayer];