UI基础 - Quartz 2D 1.2:涂鸦 | - ???


画笔涂鸦

1 - 代码示例:根据数据源(坐标),绘制路径

// - DoodleView.m

 1 #import "DoodleView.h"
 2 @implementation DoodleView
 3 
 4 - (void)drawRect:(CGRect)rect {
 5 
 6     // 得到上下文:只能在两种方式种获取到:drawRect 方法中 或者 image 图片
 7     CGContextRef context = UIGraphicsGetCurrentContext();
 8     CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);// 画笔颜色
 9     CGContextSetLineWidth(context, 2.0);// 画笔粗细
10 
11     // 搞几个坐标点
12     NSArray *pointArray = [NSArray arrayWithObjects:@[@40,@40],
13                            @[@100,@30],
14                            @[@100,@200],
15                            @[@50,@150],
16                            @[@40,@40],nil];
17 
18     for (int i = 0; i < (int)pointArray.count -1; i++) {
19         
20         CGContextMoveToPoint(context, [[[pointArray objectAtIndex:i] firstObject] floatValue], [[[pointArray objectAtIndex:i] lastObject] floatValue]);
21         CGContextAddLineToPoint(context, [[[pointArray objectAtIndex:i+1] firstObject] floatValue], [[[pointArray objectAtIndex:i+1] lastObject] floatValue]);
22     }
23 
24     CGContextStrokePath(context);
25 }
26 
27 @end

// - ViewController.m

 1 #import "ViewController.h"
 2 #import "DoodleView.h"
 3 @implementation ViewController
 4 
 5 - (void)viewDidLoad {
 6     [super viewDidLoad];
 7     
 8     DoodleView *doodleView = [[DoodleView alloc] initWithFrame:self.view.bounds];
 9     doodleView.backgroundColor = [UIColor cyanColor];
10     [self.view addSubview:doodleView];
11 
12 }
13 
14 @end

运行效果

2 - 代码示例:涂鸦

// - DoodleView.m

 1 #import "DoodleView.h"
 2 @interface DoodleView ()
 3 
 4 @property(nonatomic,strong)NSMutableArray *lineArray;// 存放所有单个路径
 5 @end
 6 
 7 @implementation DoodleView
 8 
 9 - (instancetype)initWithFrame:(CGRect)frame{
10     self = [super initWithFrame:frame];
11     if (self) {
12 
13         self.lineArray = [NSMutableArray array];
14         
15         // 取消按钮
16         UIButton *cancelBT = [UIButton buttonWithType:UIButtonTypeCustom];
17         cancelBT.frame = CGRectMake((self.frame.size.width-120)*0.5, 510, 120, 30);
18         [cancelBT setTitle:@"cancel" forState:UIControlStateNormal];
19         cancelBT.layer.cornerRadius = 10;
20         cancelBT.backgroundColor = [UIColor redColor];
21         [self addSubview:cancelBT];
22         [cancelBT addTarget:self action:@selector(makeCancel) forControlEvents:UIControlEventTouchUpInside];
23 
24     }
25     return self;
26 }
27 
28 // 撤回上次的绘图操作
29 -(void)makeCancel{
30 
31     [self.lineArray removeLastObject];
32     [self setNeedsDisplay];
33 }
34 
35 - (void)drawRect:(CGRect)rect {
36     
37     CGContextRef context = UIGraphicsGetCurrentContext();
38     CGContextSetStrokeColorWithColor(context, [UIColor greenColor].CGColor);// 画笔颜色
39     CGContextSetLineWidth(context, 2.0);
40 
41     // 首先遍历大数组 self.lineArray,获取每一条线( 所有点 )的小数组 ponitArray
42     // 再次遍历小数组中所有的点,进行绘制
43     for (int i = 0 ; i< self.lineArray.count; i ++) {
44         
45         NSMutableArray *ponitArray = [self.lineArray objectAtIndex:i];
46         
47         for (int j = 0; j < (int)ponitArray.count - 1; j++) {
48             NSValue *firstValue = [ponitArray objectAtIndex:j];
49             NSValue *secondValue = [ponitArray objectAtIndex:j+1];
50 
51             CGPoint firstPoint = [firstValue CGPointValue];
52             CGPoint secondPoint = [secondValue CGPointValue];
53 
54             CGContextMoveToPoint(context, firstPoint.x, firstPoint.y);
55             CGContextAddLineToPoint(context, secondPoint.x, secondPoint.y);
56         }
57     }
58     
59     CGContextStrokePath(context);// 渲染
60 }
61 
62 // 开始绘制:现在并没有拿到路径上具体的点,所以此时应该先用一个数组保存一条路径
63 // 每一次调用都应该是创建一个新的路径( 新的 linePathArray ),然后添加到保存所有路径的数组中( self.lineArray)
64 // 最后调用 setNeedsDisplay 方法,绘制路径
65 -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
66 
67     UITouch *touch = [touches anyObject];
68     CGPoint currentPoint = [touch locationInView:self];
69 
70     //linePathArray( 保存了一条 line )
71     NSMutableArray *linePathArray = [NSMutableArray array];
72     NSValue *ponitValue = [NSValue valueWithCGPoint:currentPoint];
73     [linePathArray addObject:ponitValue];
74     [self.lineArray addObject:linePathArray];
75     [self setNeedsDisplay];
76 }
77 
78 // 给最新添加的那个路径添加点,所以应当找到数组中最后一个路径,然后给这个路径添加 point
79 -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
80 
81     UITouch *touch = [touches anyObject];
82     CGPoint currentPoint = [touch locationInView:self];
83     NSMutableArray *lastLineArr = [self.lineArray lastObject];
84     NSValue *ponitValue = [NSValue valueWithCGPoint:currentPoint];
85     [lastLineArr addObject:ponitValue];
86     [self setNeedsDisplay];
87 }
88 
89 // 同 touchesMoved
90 -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
91     UITouch *touch = [touches anyObject];
92     CGPoint currentPoint = [touch locationInView:self];
93     NSMutableArray *lastLineArr = [self.lineArray lastObject];
94     NSValue *ponitValue = [NSValue valueWithCGPoint:currentPoint];
95     [lastLineArr addObject:ponitValue];
96     [self setNeedsDisplay];
97 }
98 
99 @end

用此方式涂鸦越频繁,会造成设备明显卡顿,如何解决 ?

// - ViewController.m

 1 #import "ViewController.h"
 2 #import "DoodleView.h"
 3 @implementation ViewController
 4 
 5 - (void)viewDidLoad {
 6     [super viewDidLoad];
 7     DoodleView *doodleView = [[DoodleView alloc] initWithFrame:self.view.bounds];
 8     doodleView.backgroundColor = [UIColor whiteColor];
 9     [self.view addSubview:doodleView];
10 }
11 
12 @end

运行效果