动画

第一篇:iOS中的贝塞尔曲线--UIBezierPath

2018-01-31  本文已影响29人  意一ineyee

在开始学习Quartz2D之前,我们先总结下UIKit框架里的UIBezierPath,可以方便我们理解后面Quartz2D的部分内容,也可以方便我们和后面Quartz2D的部分内容做对比。


目录

一、什么是贝塞尔曲线?

1、贝塞尔曲线的定义及绘制原理
2、UIBezierPath常用的Api

二、如何使用UIBezierPath?


一、什么是贝塞尔曲线?

1、贝塞尔曲线的定义及绘制原理

但是我不知道为什么UIKit里的UIBezierPath要叫UIBezierPath,看了下面,我们很明显能知道UIBezierPath不仅能用指定的方法绘制贝塞尔曲线,还能绘制别的任意你想要绘制的曲线,感觉贝塞尔曲线仅仅是UIBezierPath所能绘制的曲线的真子集。不知道是不是我没理解贝塞尔曲线的缘故,可能是我把贝塞尔曲线的范围给缩小了,因为我们知道可以绘制出一条直线,这条直线也可以看做是一条一次贝塞尔曲线,如果这样考虑的话,任意一条曲线都可以看作是一条N次贝塞尔曲线了,就能和UIBezierPath对应起来了,暂时这样考虑吧。

(1)绘制线段AC、BC,相交于点C;
(2)在线段AC上取点D,在线段BC上取点E,使得AD:DC=CE:EB;
(3)连接DE;
(4)在线段DE上取点F,使得DF:FE=AD:DC=CE:EB;

如下图:

11.png

(5)这样我们就算是找到了贝塞尔曲线上的一个点--F,按同样的道理让点D从A移动到C、点E从C移动到B,就会找到无数个点F,这样把点F连接起来就可以绘制出贝塞尔曲线。如下图:

11.gif
2、UIBezierPath常用的Api

(1)常用路径参数

[[UIColor <#someColor#>] set];// 同时设置路径颜色和路径的填充色
[[UIColor <#someColor#>] setStroke];// 设置路径颜色
[[UIColor <#someColor#>] setFill];// 设置路径的填充色

@property(nonatomic) CGFloat lineWidth;// 路径宽度
@property(nonatomic) CGLineCap lineCapStyle;// 路径开始和结尾的样式
@property(nonatomic) CGLineJoin lineJoinStyle;// 路径转角处的样式
lineCapStyle: 11.png lineJoinStyle: 11.png

(2)笨拙绘制路径的方法:虽说使用这些方法画起某些特殊的路径来比下面的特殊方法慢一点,但是毫无疑问这些方法是绘制路径的根本,所以可以绘制各种各样任何你想要的路径。

①把路径当前点移动到指定的点point:

- (void)moveToPoint:(CGPoint)point;

②画一条直线:

- (void)addLineToPoint:(CGPoint)point;

③画一段圆弧:

- (void)addArcWithCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise;
11.png

④画一条二次贝塞尔曲线:

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

⑤画一条三次贝塞尔曲线:

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

⑥画一条虚线:

- (void)setLineDash:(nullable const CGFloat *)pattern count:(NSInteger)count phase:(CGFloat)phase;

⑥闭合路径:

- (void)closePath;

(3)快速绘制特殊路径的方法:我们可以使用这些方法快速地绘制一个矩形、圆角矩形、圆弧、圆或者椭圆,而且再使用这些方法绘制路径时,不需要主动调用- (void)moveToPoint:(CGPoint)point;来设置路径的起始点,也不需要主动调用- (void)closePath;来闭合路径,这些方法都会自动的完成这两个操作。

①画一个矩形

+ (instancetype)bezierPathWithRect:(CGRect)rect;

②画一个圆角矩形(四个角都会圆)

+ (instancetype)bezierPathWithRoundedRect:(CGRect)rect cornerRadius:(CGFloat)cornerRadius;

③画一个指定圆角的矩形(指定角会圆)

+ (instancetype)bezierPathWithRoundedRect:(CGRect)rect byRoundingCorners:(UIRectCorner)corners cornerRadii:(CGSize)cornerRadii;

④画一段圆弧

+ (instancetype)bezierPathWithArcCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise;

⑤给定一个矩形,画出其内切圆或椭圆

+ (instancetype)bezierPathWithOvalInRect:(CGRect)rect;

(4)渲染路径:两种渲染可单独使用,也可以同时使用
①空心渲染路径:

- (void)stroke;

②实心渲染路径:

- (void)fill;

(5)路径的仿射变化:

- (void)applyTransform:(CGAffineTransform)transform;

(6)移除路径上所有的点(或者说移除路径):

- (void)removeAllPoints;

(7)剪裁效果:

- (void)addClip;

二、如何使用UIBezierPath?

1、画一条直线
(清单1.1)

//
//  CustomView.m
//  UIBezierPath
//
//  Created by 意一yiyi on 2018/1/29.
//  Copyright © 2018年 意一yiyi. All rights reserved.
//

#import "CustomView.h"

@implementation CustomView

- (void)drawRect:(CGRect)rect {
    
    UIBezierPath *bezierPath = [[UIBezierPath alloc] init];
    [[UIColor redColor] setStroke];
    bezierPath.lineWidth = 11;
    bezierPath.lineCapStyle = kCGLineCapButt;
    bezierPath.lineJoinStyle = kCGLineJoinRound;
    [bezierPath moveToPoint:CGPointMake(100, 100)];
    [bezierPath addLineToPoint:CGPointMake(200, 100)];
    [bezierPath stroke];
    
    UIBezierPath *bezierPath1 = [[UIBezierPath alloc] init];
    [[UIColor redColor] setStroke];
    bezierPath1.lineWidth = 11;
    bezierPath1.lineCapStyle = kCGLineCapRound;
    bezierPath1.lineJoinStyle = kCGLineJoinRound;
    [bezierPath1 moveToPoint:CGPointMake(100, 200)];
    [bezierPath1 addLineToPoint:CGPointMake(200, 200)];
    [bezierPath1 stroke];
    
    UIBezierPath *bezierPath2 = [[UIBezierPath alloc] init];
    [[UIColor redColor] setStroke];
    bezierPath2.lineWidth = 11;
    bezierPath2.lineCapStyle = kCGLineCapSquare;
    bezierPath2.lineJoinStyle = kCGLineJoinRound;
    [bezierPath2 moveToPoint:CGPointMake(100, 300)];
    [bezierPath2 addLineToPoint:CGPointMake(200, 300)];
    [bezierPath2 stroke];
}

@end
11.png

2、画圆弧、 圆、椭圆
(清单1.2)

//
//  CustomView.m
//  UIBezierPath
//
//  Created by 意一yiyi on 2018/1/29.
//  Copyright © 2018年 意一yiyi. All rights reserved.
//

#import "CustomView.h"

@implementation CustomView

- (void)drawRect:(CGRect)rect {
    
    // 画一段圆弧
    UIBezierPath *bezierPath = [[UIBezierPath alloc] init];
    [[UIColor redColor] setStroke];
    bezierPath.lineWidth = 11;
    bezierPath.lineCapStyle = kCGLineCapButt;
    bezierPath.lineJoinStyle = kCGLineJoinRound;
    [bezierPath moveToPoint:CGPointMake(150, 100)];
    [bezierPath addArcWithCenter:CGPointMake(100, 100) radius:50 startAngle:0 endAngle:M_PI_2 clockwise:YES];
    [bezierPath stroke];
    
    UIBezierPath *bezierPath1 = [UIBezierPath bezierPathWithArcCenter:CGPointMake(300, 100) radius:50 startAngle:0 endAngle:M_PI_2 clockwise:NO];
    [[UIColor orangeColor] setStroke];
    [bezierPath1 stroke];
    
    // 画圆
    UIBezierPath *bezierPath2 = [[UIBezierPath alloc] init];
    [[UIColor redColor] setStroke];
    [bezierPath2 moveToPoint:CGPointMake(150, 250)];
    [bezierPath2 addArcWithCenter:CGPointMake(100, 250) radius:50 startAngle:0 endAngle:M_PI * 2 clockwise:YES];
    [bezierPath2 stroke];
    
    UIBezierPath *bezierPath3 = [UIBezierPath bezierPathWithArcCenter:CGPointMake(300, 250) radius:50 startAngle:0 endAngle:M_PI * 2 clockwise:NO];
    [[UIColor orangeColor] setFill];
    [bezierPath3 fill];
    
    // 通过矩形来画出其内切圆或内切椭圆
    UIBezierPath *bezierPath4 = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(50, 350, 100, 100)];
    [[UIColor orangeColor] setStroke];
    [bezierPath4 stroke];

    UIBezierPath *bezierPath5 = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(250, 350, 100, 50)];
    [[UIColor orangeColor] setStroke];
    [bezierPath5 stroke];
}

@end
11.png

3、画矩形、 圆角矩形、指定圆角的圆角矩形
(清单1.3)

//
//  CustomView.m
//  UIBezierPath
//
//  Created by 意一yiyi on 2018/1/29.
//  Copyright © 2018年 意一yiyi. All rights reserved.
//

#import "CustomView.h"

@implementation CustomView

- (void)drawRect:(CGRect)rect {
    
    // 画矩形
    UIBezierPath *bezierPath = [[UIBezierPath alloc] init];
    [[UIColor redColor] setStroke];
    bezierPath.lineWidth = 11;
    bezierPath.lineCapStyle = kCGLineCapButt;
    bezierPath.lineJoinStyle = kCGLineJoinRound;
    [bezierPath moveToPoint:CGPointMake(100, 100)];
    [bezierPath addLineToPoint:CGPointMake(200, 100)];
    [bezierPath addLineToPoint:CGPointMake(200, 200)];
    [bezierPath addLineToPoint:CGPointMake(100, 200)];
    [bezierPath closePath];// 或者[bezierPath addLineToPoint:CGPointMake(100, 100)];
    [bezierPath stroke];
    
    UIBezierPath *bezierPath1 = [UIBezierPath bezierPathWithRect:CGRectMake(250, 100, 100, 100)];
    [[UIColor orangeColor] setStroke];
    [bezierPath1 stroke];
    
    // 画圆角矩形
    UIBezierPath *bezierPath2 = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(100, 250, 100, 100) cornerRadius:10];
    [[UIColor orangeColor] setStroke];
    [bezierPath2 stroke];
    
    // 画指定圆角的矩形
    UIBezierPath *bezierPath3 = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(100, 400, 100, 100) byRoundingCorners:(UIRectCornerTopLeft | UIRectCornerBottomRight) cornerRadii:CGSizeMake(40, 0)];
    [[UIColor orangeColor] setStroke];
    [bezierPath3 stroke];
}

@end
11.png

4、画二次贝塞尔曲线和三次贝塞尔曲线
(清单1.4)

//
//  CustomView.m
//  UIBezierPath
//
//  Created by 意一yiyi on 2018/1/29.
//  Copyright © 2018年 意一yiyi. All rights reserved.
//

#import "CustomView.h"

@implementation CustomView

- (void)drawRect:(CGRect)rect {
    
    // 画一条二次贝塞尔曲线
    UIBezierPath *bezierPath = [[UIBezierPath alloc] init];
    [[UIColor redColor] setStroke];
    bezierPath.lineWidth = 11;
    [bezierPath moveToPoint:CGPointMake(100, 100)];
    [bezierPath addQuadCurveToPoint:CGPointMake(300, 100) controlPoint:CGPointMake(200, 200)];
    [bezierPath stroke];
    
    // 画一条三次贝塞尔曲线
    UIBezierPath *bezierPath1 = [[UIBezierPath alloc] init];
    [[UIColor redColor] setStroke];
    bezierPath1.lineWidth = 11;
    [bezierPath1 moveToPoint:CGPointMake(100, 300)];
    [bezierPath1 addCurveToPoint:CGPointMake(300, 300) controlPoint1:CGPointMake(150, 350) controlPoint2:CGPointMake(250, 250)];
    [bezierPath1 stroke];
}

@end
11.png

5、画一条虚线
(清单1.5)

//
//  CustomView.m
//  UIBezierPath
//
//  Created by 意一yiyi on 2018/1/29.
//  Copyright © 2018年 意一yiyi. All rights reserved.
//

#import "CustomView.h"

@implementation CustomView

- (void)drawRect:(CGRect)rect {
    
    UIBezierPath *bezierPath = [[UIBezierPath alloc] init];
    [[UIColor redColor] setStroke];
    CGFloat pattern[] = {10, 10};
    [bezierPath setLineDash:pattern count:2 phase:0];
    [bezierPath moveToPoint:CGPointMake(100, 100)];
    [bezierPath addLineToPoint:CGPointMake(300, 100)];
    [bezierPath stroke];
    
    UIBezierPath *bezierPath1 = [[UIBezierPath alloc] init];
    [[UIColor redColor] setStroke];
    CGFloat pattern1[] = {10, 20, 30};
    [bezierPath1 setLineDash:pattern1 count:3 phase:0];
    [bezierPath1 moveToPoint:CGPointMake(100, 120)];
    [bezierPath1 addLineToPoint:CGPointMake(300, 120)];
    [bezierPath1 stroke];
    
    UIBezierPath *bezierPath2 = [[UIBezierPath alloc] init];
    [[UIColor redColor] setStroke];
    CGFloat pattern2[] = {10, 10};
    [bezierPath2 setLineDash:pattern2 count:2 phase:5];
    [bezierPath2 moveToPoint:CGPointMake(100, 140)];
    [bezierPath2 addLineToPoint:CGPointMake(300, 140)];
    [bezierPath2 stroke];
    
    UIBezierPath *bezierPath3 = [UIBezierPath bezierPathWithArcCenter:self.center radius:100 startAngle:0 endAngle:M_PI * 2 clockwise:YES];
    [[UIColor redColor] setStroke];
    bezierPath3.lineWidth = 11;
    CGFloat pattern3[] = {1, 10};
    [bezierPath3 setLineDash:pattern3 count:2 phase:0];
    [bezierPath3 stroke];
}

@end
11.png

6、贝塞尔曲线的仿射变换

我们发现UIBezierPath提供的方法里画的矩形只能是正的,如果我们要画一个歪的,也可以通过贝塞尔曲线的仿射变换来实现。

(清单1.6)

//
//  CustomView.m
//  UIBezierPath
//
//  Created by 意一yiyi on 2018/1/29.
//  Copyright © 2018年 意一yiyi. All rights reserved.
//

#import "CustomView.h"

@implementation CustomView

- (void)drawRect:(CGRect)rect {
    
    UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRect:CGRectMake(250, 100, 100, 100)];
    [[UIColor orangeColor] setStroke];
    bezierPath.lineWidth = 11;
    bezierPath.lineCapStyle = kCGLineCapButt;
    bezierPath.lineJoinStyle = kCGLineJoinRound;
    [bezierPath applyTransform:CGAffineTransformMakeRotation(M_PI_4)];
    [bezierPath stroke];
}

@end
11.png

7、剪裁路径覆盖的区域
(清单1.7)

//
//  CustomView.m
//  Quartz2D
//
//  Created by 意一yiyi on 2018/2/5.
//  Copyright © 2018年 意一yiyi. All rights reserved.
//

#import "CustomView.h"

@implementation CustomView

- (void)drawRect:(CGRect)rect {
    
    // 把图片切成任意你想要的形状显示
    UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(100, 100, 100, 100) byRoundingCorners:(UIRectCornerTopLeft | UIRectCornerBottomRight) cornerRadii:CGSizeMake(40, 0)];
    [[UIColor orangeColor] setStroke];
    [bezierPath stroke];
    [bezierPath addClip];// 剪裁路径覆盖的区域
    
    UIImage *image = [UIImage imageNamed:@"1.png"];
    [image drawAtPoint:CGPointMake(100, 100)];
}

@end
原图 效果图

8、利用- (void)addLineToPoint:(CGPoint)point;画数学函数曲线
(清单1.8)

//
//  CustomView.m
//  UIBezierPath
//
//  Created by 意一yiyi on 2018/1/29.
//  Copyright © 2018年 意一yiyi. All rights reserved.
//

#import "CustomView.h"

#define kScreenWidth [UIScreen mainScreen].bounds.size.width
#define kScreenHeight [UIScreen mainScreen].bounds.size.height

@interface CustomView ()

@property (assign, nonatomic) float waveAmplitude;// 振幅
@property (assign, nonatomic) float waveSpeed;// 波纹流动的速度
@property (assign, nonatomic) float waveOffset;// 初相

@end

@implementation CustomView

- (instancetype)initWithFrame:(CGRect)frame {
    
    if (self = [super initWithFrame:frame]) {
        
        // 初始值
        self.waveAmplitude = 20;
        self.waveSpeed = 2.0;
        self.waveOffset = 0.0;
        
        CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(wave)];
        [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:(NSRunLoopCommonModes)];
    }
    
    return self;
}

- (void)drawRect:(CGRect)rect {
    
    self.waveOffset += self.waveSpeed;
    
    UIBezierPath *bezierPath = [[UIBezierPath alloc] init];
    [[UIColor redColor] setStroke];
    bezierPath.lineWidth = 1;
    
    // 起始点
    [bezierPath moveToPoint:CGPointMake(0, self.waveAmplitude)];
    
    // 连接各点
    for (CGFloat x = 0.0; x < kScreenWidth; x ++) {
        
        CGFloat y = 100 + self.waveAmplitude * sinf(3 * M_PI * x / kScreenWidth + self.waveOffset * M_PI / kScreenWidth);
        [bezierPath addLineToPoint:CGPointMake(x, y)];
    }
    
    // 渲染
    [bezierPath stroke];
}

- (void)wave {
    
    [self setNeedsDisplay];
}

@end
1.gif

9、利用- (void)addLineToPoint:(CGPoint)point;画任意想要的曲线
(清单1.9)

//
//  CustomView.m
//  UIBezierPath
//
//  Created by 意一yiyi on 2018/1/29.
//  Copyright © 2018年 意一yiyi. All rights reserved.
//

#import "CustomView.h"

#define kScreenWidth [UIScreen mainScreen].bounds.size.width
#define kScreenHeight [UIScreen mainScreen].bounds.size.height

@interface CustomView ()

@property (strong, nonatomic) UIBezierPath *bezierPath;

@end

@implementation CustomView

- (instancetype)initWithFrame:(CGRect)frame {
    
    if (self = [super initWithFrame:frame]) {
        
        self.bezierPath = [[UIBezierPath alloc] init];
        self.bezierPath.lineWidth = 1;// 笔的粗细
    
        
        UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
        panGesture.maximumNumberOfTouches = 1;// 一个指头画
        [self addGestureRecognizer:panGesture];
    }
    
    return self;
}

- (void)pan:(UIPanGestureRecognizer *)panGesture {
    
    // 获取平移到的点
    CGPoint currentPoint = [panGesture locationInView:self];
    
    if (panGesture.state == UIGestureRecognizerStateBegan) {
        
        // 设置起始点
        [self.bezierPath moveToPoint:currentPoint];
    }else if (panGesture.state == UIGestureRecognizerStateChanged) {
        
        // 连接平移点
        [self.bezierPath addLineToPoint:currentPoint];
    }
    
    // 触发-drawRect:方法
    [self setNeedsDisplay];
}

- (void)drawRect:(CGRect)rect {
    
    // 笔的颜色
    [[UIColor redColor] setStroke];
    
    // 渲染出曲线
    [self.bezierPath stroke];
}

@end
1.gif 1.png

10、利用三次贝塞尔曲线减少曲线的锯齿,使曲线更加平滑

参考地址:消灭画线条时的锯齿

(清单1.10)

//
//  CustomView.m
//  UIBezierPath
//
//  Created by 意一yiyi on 2018/1/29.
//  Copyright © 2018年 意一yiyi. All rights reserved.
//

#import "CustomView.h"

#define kScreenWidth [UIScreen mainScreen].bounds.size.width
#define kScreenHeight [UIScreen mainScreen].bounds.size.height

CGPoint pointArray[4];// 获取我们滑动手指时的四  个点,用来做三次贝塞尔曲线
NSInteger pointIndex;// 点的下标

@interface CustomView ()

@property (strong, nonatomic) UIBezierPath *bezierPath;

@end

@implementation CustomView

- (instancetype)initWithFrame:(CGRect)frame {
    
    if (self = [super initWithFrame:frame]) {

        self.bezierPath = [[UIBezierPath alloc] init];
        self.bezierPath.lineWidth = 1;// 笔的粗细
    
        UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
        panGesture.maximumNumberOfTouches = 1;// 一个指头画
        [self addGestureRecognizer:panGesture];
    }
    
    return self;
}

- (void)pan:(UIPanGestureRecognizer *)panGesture {
    
    if (panGesture.state == UIGestureRecognizerStateBegan) {
        
        pointIndex = 0;
        
        // 获取到第一个点
        CGPoint currentPoint = [panGesture locationInView:self];
        pointArray[0] = currentPoint;

        // 设置起始点
        [self.bezierPath moveToPoint:pointArray[0]];
    }else if (panGesture.state == UIGestureRecognizerStateChanged) {
        
        pointIndex ++;
        
        // 获取平移到的点
        CGPoint currentPoint = [panGesture locationInView:self];
        pointArray[pointIndex] = currentPoint;
        
        if (pointIndex == 3) {// 获取够四个点了
            
            // 通过三次贝塞尔曲线而不是-addLineToPoint:连接平移的点,可以使得线条有更少的锯齿,更加平滑
            [self.bezierPath addCurveToPoint:pointArray[3] controlPoint1:pointArray[1] controlPoint2:pointArray[2]];
            
            // 触发-drawRect:方法
            [self setNeedsDisplay];

            // 获取下一波的四个点
            pointIndex = 0;
            pointArray[0] = [self.bezierPath currentPoint];
        }
    }
}

- (void)drawRect:(CGRect)rect {
    
    // 笔的颜色
    [[UIColor blackColor] setStroke];
    
    // 渲染出曲线
    [self.bezierPath stroke];
}

@end
1.gif 11.png

(清单1.11)

//
//  CustomView.m
//  UIBezierPath
//
//  Created by 意一yiyi on 2018/1/29.
//  Copyright © 2018年 意一yiyi. All rights reserved.
//

#import "CustomView.h"

#define kScreenWidth [UIScreen mainScreen].bounds.size.width
#define kScreenHeight [UIScreen mainScreen].bounds.size.height

CGPoint pointArray[5];// 获取我们滑动手指时的五个点,用来做三次贝塞尔曲线
NSInteger pointIndex;// 点的下标

@interface CustomView ()

@property (strong, nonatomic) UIBezierPath *bezierPath;

@end

@implementation CustomView

- (instancetype)initWithFrame:(CGRect)frame {
    
    if (self = [super initWithFrame:frame]) {
        
        self.bezierPath = [[UIBezierPath alloc] init];
        self.bezierPath.lineWidth = 1;// 笔的粗细
        
        UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
        panGesture.maximumNumberOfTouches = 1;// 一个指头画
        [self addGestureRecognizer:panGesture];
    }
    
    return self;
}

- (void)pan:(UIPanGestureRecognizer *)panGesture {
    
    if (panGesture.state == UIGestureRecognizerStateBegan) {
        
        pointIndex = 0;
        
        // 获取到第一个点
        CGPoint currentPoint = [panGesture locationInView:self];
        pointArray[0] = currentPoint;
        
        // 设置起始点
        [self.bezierPath moveToPoint:pointArray[0]];
    }else if (panGesture.state == UIGestureRecognizerStateChanged) {
        
        pointIndex ++;
        
        // 获取平移到的点
        CGPoint currentPoint = [panGesture locationInView:self];
        pointArray[pointIndex] = currentPoint;
        
        if (pointIndex == 4) {// 获取够五个点了
            
            // 重新设置3点
            pointArray[3] = CGPointMake((pointArray[2].x + pointArray[4].x) / 2.0, (pointArray[2].y + pointArray[4].y) / 2.0);
            
            // 通过三次贝塞尔曲线而不是-addLineToPoint:连接平移的点,可以使得线条有更少的锯齿,更加平滑
            [self.bezierPath addCurveToPoint:pointArray[3] controlPoint1:pointArray[1] controlPoint2:pointArray[2]];
        }
        
        // 获取下一波的四个点
        pointIndex = 1;
        pointArray[0] = pointArray[3];
        pointArray[1] = pointArray[4];
    }
    
    // 触发-drawRect:方法
    [self setNeedsDisplay];
}

- (void)drawRect:(CGRect)rect {
    
    // 笔的颜色
    [[UIColor blackColor] setStroke];
    
    // 渲染出曲线
    [self.bezierPath stroke];
}

@end
1.gif 11.png
上一篇下一篇

猜你喜欢

热点阅读