UI基础 - Quartz 2D 02:绘制 | 涂鸦 | 拖动图片
绘制路径
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 - 使用此方式进行涂鸦,操作频繁会造成设备卡顿
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 }
运行效果:将图片拖动到右上方
分类:
UI章节
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)