基础知识
使用UIBezierPath可以创建基于矢量的路径,此类是Core Graphics框架关于路径的封装。使用此类可以定义简单的形状,如椭圆、矩形或者有多个直线和曲线段组成的形状等。
UIBezierPath是CGPathRef数据类型的封装。如果是基于矢量形状的路径,都用直线和曲线去创建。我们使用直线段去创建矩形和多边形,使用曲线去创建圆弧(arc)、圆或者其他复杂的曲线形状。
使用UIBezierPath画图步骤:
1.创建一个UIBezierPath对象
2.调用-moveToPoint:设置初始线段的起点
3.添加线或者曲线去定义一个或者多个子路径
4.改变UIBezierPath对象跟绘图相关的属性。如,我们可以设置画笔的属性、填充样式等
5.根据我们设置的各个点连线 [path stroke];
下面介绍几种方法:
/*
1.可以根据我们的需要任意定制样式,可以画任何我们想画的图形
+ (instancetype)bezierPath;
*/
/*
2.创建出圆形贝塞尔曲线 这个方法是根据一个矩形画内切曲线。通常用它来画圆或者椭圆
+ (instancetype)bezierPathWithOvalInRect:(CGRect)rect;
*/
/*
3.根据一个矩形画贝塞尔曲线
+ (instancetype)bezierPathWithRect:(CGRect)rect;
*/
/*
4.画矩形,但是这个矩形是可以画圆角的。第一个参数是矩形,第二个参数是圆角大小
+ (instancetype)bezierPathWithRoundedRect:(CGRect)rect
cornerRadius:(CGFloat)cornerRadius;
*/
/*
5.这个方法也是画矩形,这个矩形是可以画圆角的,但是可以指定某一个角画成圆角
byRoundingCorners:
UIRectCornerTopLeft = 1 << 0,
UIRectCornerTopRight = 1 << 1,
UIRectCornerBottomLeft = 1 << 2,
UIRectCornerBottomRight = 1 << 3,
UIRectCornerAllCorners = ~0UL
cornerRadii:
CGFloat width;
CGFloat height;
+ (instancetype)bezierPathWithRoundedRect:(CGRect)rect
byRoundingCorners:(UIRectCorner)corners
cornerRadii:(CGSize)cornerRadii;
*/
/*
6.这个工厂方法用于画弧,参数说明如下: center: 弧线中心点的坐标 radius: 弧线所在圆的半径 startAngle: 弧线开始的弧度值 endAngle: 弧线结束的弧度值 clockwise: 是否顺时针画弧线 startAngle和endAngle使用的是弧度,而不是角度,因此我们需要将常用的角度转换成弧度
+ (instancetype)bezierPathWithArcCenter:(CGPoint)center
radius:(CGFloat)radius
startAngle:(CGFloat)startAngle
endAngle:(CGFloat)endAngle
clockwise:(BOOL)clockwise;
*/
//注意:使用UIBezierPath画路径,应该在一个继承于UIView的view中的 - (void)drawRect:(CGRect)rect方法中进行使用,然后再在控制器中调用这个自定义的view即可
下面上代码来看使用及实现效果:
创建一个BezierPathView继承于UIView:
#import <UIKit/UIKit.h>
@interface BezierPathView : UIView
@end
#import "BezierPathView.h"
#define kDegreesToRadians(degress) ((pi *degress)/180)
@implementation BezierPathView
- (void)drawRect:(CGRect)rect {
[self drawTrinangle];//画三角形
}
-(void)drawTrinangle{
UIBezierPath *trinanglePath = [UIBezierPath bezierPath];
[trinanglePath moveToPoint:CGPointMake(50, 50)];//起始点
[trinanglePath addLineToPoint:CGPointMake(100, 50)];//添加子路径
[trinanglePath addLineToPoint:CGPointMake(75, 100)];
[trinanglePath closePath];//最后的闭合线是可以通过调用closePath方法来自动生成的
//也可以调用-addLineToPoint:方法来添加
// [trinanglePath addLineToPoint:CGPointMake(50, 50)];
//设置线宽
trinanglePath.lineWidth = 1;
//设置填充颜色
UIColor *color = [UIColor redColor];
[color set];
[trinanglePath fill];
//设置画笔颜色
UIColor *strokeColor = [UIColor blueColor];
[strokeColor set];
//根据设置的各个点连线
[trinanglePath stroke];
}
ViewController中进行调用:
#import "ViewController.h"
#import "BezierPathView.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
BezierPathView *bezierView = [[BezierPathView alloc]initWithFrame:CGRectMake(50, 50, 200, 200)];
[self.view addSubview:bezierView];
bezierView.backgroundColor = [UIColor yellowColor];
}
效果图:
画矩形:
// 画矩形
- (void)drawRectPath {
UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(20, 20, self.frame.size.width - 40, self.frame.size.height - 40)];
path.lineWidth = 1.5;
path.lineCapStyle = kCGLineCapRound;
path.lineJoinStyle = kCGLineJoinBevel;
// 设置填充颜色
UIColor *fillColor = [UIColor greenColor];
[fillColor set];
[path fill];
// 设置画笔颜色
UIColor *strokeColor = [UIColor blueColor];
[strokeColor set];
// 根据我们设置的各个点连线
[path stroke];
}
/**
lineCapStyle属性是用来设置线条拐角帽的样式的,其中有三个选择:
typedef CF_ENUM(int32_t, CGLineCap) {
kCGLineCapButt,
kCGLineCapRound,
kCGLineCapSquare
};
其中,第一个是默认的,第二个是轻微圆角,第三个正方形
lineJoinStyle属性是用来设置两条线连结点的样式,其中也有三个选择:
typedef CF_ENUM(int32_t, CGLineJoin) {
kCGLineJoinMiter,
kCGLineJoinRound,
kCGLineJoinBevel
};
其中,第一个是默认的表示斜接,第二个是圆滑衔接,第三个是斜角连接。
*/
画圆:
- (void)drawCiclePath {
// 传的是正方形,因此就可以绘制出圆了
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(20, 20, self.frame.size.width - 40, self.frame.size.width - 40)];//要画圆,我们需要传的rect参数必须是正方形哦!
// 设置填充颜色
UIColor *fillColor = [UIColor greenColor];
[fillColor set];
[path fill];
// 设置画笔颜色
UIColor *strokeColor = [UIColor blueColor];
[strokeColor set];
// 根据我们设置的各个点连线
[path stroke];
}
画椭圆:
// 画椭圆
- (void)drawOvalPath {
// 传的是不是正方形,因此就可以绘制出椭圆圆了
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(20, 20, self.frame.size.width - 80, self.frame.size.height - 40)];
// 设置填充颜色
UIColor *fillColor = [UIColor greenColor];
[fillColor set];
[path fill];
// 设置画笔颜色
UIColor *strokeColor = [UIColor blueColor];
[strokeColor set];
// 根据我们设置的各个点连线
[path stroke];
}
画弧
//画弧
- (void)drawARCPath {
const CGFloat pi = 3.14159265359;
CGPoint center = CGPointMake(self.frame.size.width / 2, self.frame.size.height / 2);
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center
radius:100
startAngle:0
endAngle:kDegreesToRadians(135)
clockwise:YES];
path.lineCapStyle = kCGLineCapRound;
path.lineJoinStyle = kCGLineJoinRound;
path.lineWidth = 5.0;
UIColor *strokeColor = [UIColor redColor];
[strokeColor set];
// 根据我们设置的各个点连线
[path stroke];
}
/*
画弧参数startAngle和endAngle使用的是弧度,而不是角度,因此我们需要将常用的角度转换成弧度。对于效果图中,我们设置弧的中心为控件的中心,起点弧度为0,也就是正东方向,而终点是135度角的位置。
*/
画二次贝塞尔曲线
画二次贝塞尔曲线的步骤:
先设置一个起始点,也就是通过-moveToPoint:设置
调用-addQuadCurveToPoint:controlPoint:方法设置终端点和控制点,以画二次曲线
在效果图中,拱桥左边的起始点就是我们设置的起始点,最右边的终点,就是我们设置的终端点,而我们设置的控制点为(width / 2, 0)对应于红色矩形中水平方向在正中央,而垂直方向在最顶部。
这个样式看起来很像sin或者cos函数吧?这两个只是特例而已,其实可以画任意图形,只是想不到,没有做不到的。
- (void)drawSecondBezierPath {
UIBezierPath *path = [UIBezierPath bezierPath];
// 首先设置一个起始点
[path moveToPoint:CGPointMake(20, self.frame.size.height - 100)];
// 添加二次曲线
[path addQuadCurveToPoint:CGPointMake(self.frame.size.width - 20, self.frame.size.height - 100)
controlPoint:CGPointMake(self.frame.size.width / 2, 0)];
/*
- (void)addQuadCurveToPoint:(CGPoint)endPoint controlPoint:(CGPoint)controlPoint
参数说明:
endPoint:终端点
controlPoint:控制点,对于二次贝塞尔曲线,只有一个控制点
*/
path.lineCapStyle = kCGLineCapRound;
path.lineJoinStyle = kCGLineJoinRound;
path.lineWidth = 5.0;
UIColor *strokeColor = [UIColor redColor];
[strokeColor set];
// 根据我们设置的各个点连线
[path stroke];
}
画三次贝塞尔曲线
/**
*
贝塞尔曲线必定通过首尾两个点,称为端点;中间两个点虽然未必要通过,但却起到牵制曲线形状路径的作用,称作控制点
提示:其组成是起始端点+控制点1+控制点2+终止端点
如下方法就是画三次贝塞尔曲线的关键方法,以三个点画一段曲线,一般和-moveToPoint:配合使用。
- (void)addCurveToPoint:(CGPoint)endPoint
controlPoint1:(CGPoint)controlPoint1
controlPoint2:(CGPoint)controlPoint2
*/
- (void)drawThirdBezierPath {
UIBezierPath *path = [UIBezierPath bezierPath];
// 设置起始端点
[path moveToPoint:CGPointMake(20, 150)];
[path addCurveToPoint:CGPointMake(300, 150)
controlPoint1:CGPointMake(160, 0)
controlPoint2:CGPointMake(160, 250)];
path.lineCapStyle = kCGLineCapRound;
path.lineJoinStyle = kCGLineJoinRound;
path.lineWidth = 5.0;
UIColor *strokeColor = [UIColor redColor];
[strokeColor set];
// 根据我们设置的各个点连线
[path stroke];
}
注意:
如果我们需要设置填充颜色,比如这里设置为绿色,那么我们需要在设置画笔颜色之前先设置填充颜色,否则画笔颜色就被填充颜色替代了。也就是说,如果要让填充颜色与画笔颜色不一样,那么我们的顺序必须是先设置填充颜色再设置画笔颜色。如下,这两者顺序不能改变。因为我们设置填充颜色也是跟设置画笔颜色一样调用UIColor的-set方法。
// 设置填充颜色
UIColor *fillColor = [UIColor greenColor];
[fillColor set];
[path fill];
// 设置画笔颜色
UIColor *strokeColor = [UIColor blueColor];
[strokeColor set];