首页 > 技术文章 > UI绘图 - Quartz 2D 02:涂鸦 | 拖动图片

self-epoch 2021-07-09 19:01 原文

涂鸦

1 - 代码示例

① 根据坐标点(数组)绘制路径

 1 - (void)drawRect:(CGRect)rect {
 2 
 3     CGContextRef context = UIGraphicsGetCurrentContext();
 4     CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
 5     CGContextSetLineWidth(context, 2.0);
 6 
 7     // 搞几个坐标点
 8     NSArray *pointArray = [NSArray arrayWithObjects:@[@40,@40],
 9                            @[@100,@30],
10                            @[@100,@200],
11                            @[@50,@150],
12                            @[@40,@40],nil];
13 
14     for (int i = 0; i < (int)pointArray.count -1; i++) {
15 
16         CGContextMoveToPoint(context, [[[pointArray objectAtIndex:i] firstObject] floatValue], [[[pointArray objectAtIndex:i] lastObject] floatValue]);
17         CGContextAddLineToPoint(context, [[[pointArray objectAtIndex:i+1] firstObject] floatValue], [[[pointArray objectAtIndex:i+1] lastObject] floatValue]);
18     }
19 
20     CGContextStrokePath(context);
21 }

运行效果

② 涂鸦:通过此方式进行涂鸦,操作频繁会造成设备卡顿问题

 1 #import "QuartsView.h"
 2 @interface QuartsView ()
 3 
 4 @property(nonatomic,strong)NSMutableArray *lineArray;// 存放所有单个路径
 5 @end
 6 
 7 @implementation QuartsView
 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     // 涂鸦思路
42     // 首先遍历大数组 self.lineArray,获取每一条线(所有点)的小数组 ponitArray
43     // 再次遍历小数组中所有的点,进行绘制
44     for (int i = 0 ; i< self.lineArray.count; i ++) {
45 
46         NSMutableArray *ponitArray = [self.lineArray objectAtIndex:i];
47 
48         for (int j = 0; j < (int)ponitArray.count - 1; j++) {
49             
50             NSValue *firstValue  = [ponitArray objectAtIndex:j];
51             NSValue *secondValue = [ponitArray objectAtIndex:j+1];
52 
53             CGPoint firstPoint  = [firstValue CGPointValue];
54             CGPoint secondPoint = [secondValue CGPointValue];
55 
56             CGContextMoveToPoint(context, firstPoint.x, firstPoint.y);
57             CGContextAddLineToPoint(context, secondPoint.x, secondPoint.y);
58         }
59     }
60 
61     CGContextStrokePath(context);
62 }
63 
64 // 开始绘制:现在并没有拿到路径上具体的点,此时应该先用一个数组保存一条路径
65 // 每一次调用都应该是创建一个新的路径( 新的 linePathArray ),然后添加到保存所有路径的数组中(self.lineArray)
66 // 最后调用 setNeedsDisplay 方法,绘制路径
67 -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
68 
69     UITouch *touch = [touches anyObject];
70     CGPoint currentPoint = [touch locationInView:self];
71 
72     //linePathArray(保存了一条 line)
73     NSMutableArray *linePathArray = [NSMutableArray array];
74     NSValue *ponitValue = [NSValue valueWithCGPoint:currentPoint];
75     [linePathArray addObject:ponitValue];
76     [self.lineArray addObject:linePathArray];
77     [self setNeedsDisplay];
78 }
79 
80 // 给最新添加的那个路径添加点,所以应当找到数组中最后一个路径,然后给这个路径添加 point
81 -(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
82 
83     UITouch *touch = [touches anyObject];
84     CGPoint currentPoint = [touch locationInView:self];
85     NSMutableArray *lastLineArr = [self.lineArray lastObject];
86     NSValue *ponitValue = [NSValue valueWithCGPoint:currentPoint];
87     [lastLineArr addObject:ponitValue];
88     [self setNeedsDisplay];
89 }

运行效果:涂鸦

拖动图片

// - QuartsView.h

 1 #import <UIKit/UIKit.h>
 2 @interface QuartsView : UIView
 3 
 4 @property CGPoint firstTouch;// 开始时触摸点
 5 @property CGPoint lastTouch; // 结束时触摸点
 6 @property CGRect redrawRect; // 重绘区域
 7 
 8 @property(nonatomic,assign) BOOL locked;// 锁定图片起始位置
 9 @property(nonatomic,strong)UIImage *drawImage; // 拖动的图片
10 
11 @end

// - QuartsView.m

 1 #import "QuartsView.h"
 2 @implementation QuartsView
 3 - (void)drawRect:(CGRect)rect{
 4 
 5     static dispatch_once_t oneToken;
 6     dispatch_once(&oneToken, ^{
 7         self.locked = NO;
 8         CGPoint beginPoint = CGPointMake(100, 150);
 9         [_drawImage drawAtPoint:beginPoint];
10     });
11 
12     if (self.locked) {
13         CGFloat horizontalOffset = _drawImage.size.width/2.0;
14         CGFloat verticalOffset   = _drawImage.size.height/2.0;
15         CGPoint drawPoint = CGPointMake(_lastTouch.x - horizontalOffset, _lastTouch.y - verticalOffset);
16         [_drawImage drawAtPoint:drawPoint];
17     }
18 
19 }
20 
21 // 开始
22 -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
23     self.locked = YES;
24     UITouch *touch = [touches anyObject];
25     _firstTouch = [touch locationInView:self];
26     _lastTouch  = [touch locationInView:self];
27     [self setNeedsDisplay];
28 }
29 
30 // 移动
31  -(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
32 
33         UITouch *touch = [touches anyObject];
34      _lastTouch = [touch locationInView:self];
35 
36      CGFloat horizontalOffset = _drawImage.size.width/2.0;
37      CGFloat verticalOffset = _drawImage.size.height/2.0;
38      _redrawRect = CGRectUnion(_redrawRect, CGRectMake(_lastTouch.x - horizontalOffset, _lastTouch.y - verticalOffset, _drawImage.size.width, _drawImage.size.height));
39      [self setNeedsDisplayInRect:_redrawRect];
40 }
41 
42 @end

// - ViewController.m

1 @interface ViewController()
2 @property(nonatomic,strong)QuartsView *QV;
3 @end
 1 - (void)viewDidLoad{
 2     [super viewDidLoad];
 3 
 4     // 画布
 5     self.navigationController.navigationBar.hidden = YES;
 6     self.QV = [[QuartsView alloc] initWithFrame:self.view.frame];
 7     self.QV.backgroundColor = [UIColor cyanColor];
 8     self.QV.drawImage = [UIImage imageNamed:@"狗子.jpeg"];
 9     [self.view addSubview:self.QV];
10     
11 }

运行效果:将图片拖动到右上方

 

推荐阅读