比來在進修Quartz2D,進修了一個簡略畫板的完成,如今把完成進程記載一下。
重要用到的點就是畫線,截屏,繪制圖片,選擇圖片,和保留一切繪制的線。
起首在storyboard上結構好控件,設置束縛等等,最初的後果是如許:
自界說畫板DrawView,應用時能夠是從xib中加載,也能夠是手動創立,所以創立對象的辦法須要完成兩個:
#import <UIKit/UIKit.h> @interface DrawView : UIView /** 線寬 */ @property (nonatomic, assign) NSInteger lineWidth; /** 色彩 */ @property(nonatomic, strong) UIColor *pathColor; /** 圖片 */ @property(nonatomic, strong) UIImage *image; - (void)clear; - (void)undo;
- (void)awakeFromNib { [self setUp]; } - (instancetype)initWithFrame:(CGRect)frame { if (self == [super initWithFrame:frame]) { [self setUp]; } return self; }
setUp初始化辦法,初始化時要做的工作就是給畫板添加拖著手勢,也能夠將畫筆途徑的線寬在這裡設置
//自界說初始化辦法 - (void)setUp { //添加手勢 UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]initWithtarget:self action:@selector(pan:)]; [self addGestureRecognizer:pan]; //初始化時設置途徑線寬 _lineWidth = 2; }
手指在畫板上挪動時開端繪制線條,這裡由於原生的UIBezierPath類沒有方法設置途徑色彩,所以這裡只能自界說Path類了
#import <UIKit/UIKit.h> @interface DrawPath : UIBezierPath @property (nonatomic, strong) UIColor *pathColor; @end
手指挪動時,繪制線條,途徑是自界說的Path類
@interface DrawView () @property(nonatomic, strong)DrawPath *path; /** 保留一切途徑的數組 */ @property(nonatomic, strong) NSMutableArray *pathArr; @end //懶加載 - (NSMutableArray *)pathArr { if (_pathArr == nil) { _pathArr = [NSMutableArray array]; } return _pathArr; }
- (void)pan:(UIPanGestureRecognizer *)pan { //獲得開端的觸摸點 CGPoint startP = [pan locationInView:self]; if (pan.state == UIGestureRecognizerStateBegan) { //創立貝塞爾途徑 _path = [[DrawPath alloc]init]; _path.lineWidth = _lineWidth; _path.pathColor = _pathColor; //不克不及在手指抬起時將途徑添加到數組,由於在遍歷數組畫線時途徑還沒有被添加到數組外面 [_pathArr addObject:_path]; //設置終點 [_path moveToPoint:startP]; } //連線 [_path addL.netoPoint:startP]; //重繪,挪用drawRect辦法 [self setNeedsDisplay]; }
畫線完成drawRect辦法,繪制線條或許圖片時,是把數組中的途徑全體畫出來
- (void)drawRect:(CGRect)rect { //把一切途徑畫出來 for (DrawPath *path in self.pathArr) { if ([path isKindOfClass:[UIImage class]]) { //繪圖 UIImage *image = (UIImage *)path; [image draWinRect:rect]; }else { //畫線 [path.pathColor set]; [path stroke]; } } }
當把圖片添加到畫板時
- (void)setImage:(UIImage *)image { _image = image; [self.pathArr addObject:image]; //重繪挪用drawRect能力在畫板上顯示圖片 [self setNeedsDisplay]; }
還可以把直接更新途徑數組的操作封裝在畫板中
- (void)clear { //消除 [self.pathArr removeAllObjects]; [self setNeedsDisplay]; } - (void)undo { //撤消 [self.pathArr removeLastObject]; [self setNeedsDisplay]; }
掌握器中:
@interface ViewController () <UIImagePickerControllerDelegate, UINavigationControllerDelegate> @property (weak, nonatomic) IBOutlet DrawView *drawView; @end
完成幾個按鈕對畫板的操作:
- (IBAction)clear:(id)sender { //清屏 [_drawView clear]; } - (IBAction)undo:(id)sender { //撤消 [_drawView undo]; } - (IBAction)eraser:(id)sender { //擦除 就是把途徑的色彩設置為畫板的配景色,假象 _drawView.pathColor = _drawView.backgroundColor; _drawView.lineWidth = 20; } - (IBAction)changeLineWidth:(UISlider *)sender { //轉變途徑線寬 _drawView.lineWidth = sender.value; } - (IBAction)changeColor:(UIButton *)sender { //轉變途徑色彩 _drawView.pathColor = sender.backgroundColor; } - (IBAction)pickPhoto:(id)sender { //選擇照片 //彈出體系相冊 UIImagePickerController *picker = [[UIImagePickerController alloc]init]; //設置選擇掌握器的起源 UIImagePickerControllerSourceTypeSavedPhotosAlbum:照片庫 picker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum; //設置署理 picker.delegate = self; //modal出掌握器 [self presentViewController:picker animated:YES completion:nil]; } - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info { //獲得選擇的圖片 UIImage *image = info[UIImagePickerControllerOriginalImage]; //創立一個處置圖片的view ImageHandleView *handleView = [[ImageHandleView alloc]initWithFrame:self.drawView.bounds]; handleView.handleCompletionBlock = ^(UIImage *image){ _drawView.image = image; }; [self.drawView addSubview:handleView]; //將圖片畫在畫板上 handleView.image = image; //_drawView.image = image; //dismiss [self dismissViewControllerAnimated:YES completion:nil]; //NSLog(@"%@", info); } - (IBAction)save:(id)sender { [UIView animateWithDuration:0.15 animations:^{ //保留以後畫板上的內容 //開啟高低文 UIGraphicsBeginImageContextWithOptions(_drawView.bounds.size, NO, 0); //獲得位圖高低文 CGContextRef ctx = UIGraphicsGetCurrentContext(); //把控件上的圖層襯著到高低文 [_drawView.layer renderInContext:ctx]; //獲得高低文中的圖片 UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); //封閉高低文 UIGraphicsEndImageContext(); //保留圖片到相冊 UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil); self.drawView.alpha = 0; } completion:^(BOOL finished) { [UIView animateWithDuration:0.15 animations:^{ self.drawView.alpha = 1; }]; }]; } //保留勝利後的辦法必需是這個,不克不及隨意寫 - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo { NSLog(@"保留勝利"); }
從相冊選擇完圖片後把圖片顯示在畫板上了然則還沒有襯著到layer,這時候候須要對圖片停止挪動縮放扭轉這些操作的話,然則UIImage是不克不及拉伸扭轉這些操作的,UIImageView才可以,所以處理思緒就是自界說一個view來專門處置對圖片的操作,在自界說view上放一個UIImageView,從相冊選擇圖片後獲得的image設置給UIImageView,如許的自界說view上操作UIIamgeView。
#import <UIKit/UIKit.h> @interface ImageHandleView : UIView /** 圖片 */ @property(nonatomic, strong) UIImage *image; /** block */ @property(nonatomic, strong) void(^handleCompletionBlock)(UIImage *image); @end
#import "ImageHandleView.h" @interface ImageHandleView () <UIGestureRecognizerDelegate> /** image */ @property(nonatomic, weak) UIImageView *imageView; @end @implementation ImageHandleView //避免圖片上的觸摸事宜傳遞到畫板 - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { return _imageView; } - (UIImageView *)imageView { if (_imageView == nil) { UIImageView *imageV = [[UIImageView alloc]initWithFrame:self.bounds]; _imageView = imageV; //設置imgaeview許可與用戶交互 _imageView.userInteractionEnabled = YES; //添加手勢 [self setUpGestureRecognizer]; //把這個imageview添加到圖片處置的view上 [self addSubview:imageV]; } return _imageView; } #pragma mark - 添加手勢 - (void)setUpGestureRecognizer { //平移手勢 UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]initWithtarget:self action:@selector(pan:)]; [_imageView addGestureRecognizer:pan]; //扭轉手勢 UIRotationGestureRecognizer *rotation = [[UIRotationGestureRecognizer alloc]initWithtarget:self action:@selector(rotation:)]; rotation.delegate = self; [_imageView addGestureRecognizer:rotation]; //縮撒手勢 UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(pinch:)]; pinch.delegate = self; [_imageView addGestureRecognizer:pinch]; //長按手勢 UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(longPress:)]; [_imageView addGestureRecognizer:longPress]; } #pragma mark - 處置平移手勢 - (void)pan:(UIPanGestureRecognizer *)pan { //獲得手指的偏移量 CGPoint tranp = [pan translationInView:self.imageView]; //設置imageview的形變 self.imageView.transform = CGAff.netransformTranslate(self.imageView.transform, tranp.x, tranp.y); //復位 [pan setTranslation:CGPointZero inView:self.imageView]; } #pragma mark - 處置扭轉手勢 - (void)rotation:(UIRotationGestureRecognizer *)rotation { //設置imageview的形變 self.imageView.transform = CGAffineTransformRotate(self.imageView.transform, rotation.rotation); //復位 rotation.rotation = 0; } #pragma mark - 處置縮撒手勢 - (void)pinch:(UIPinchGestureRecognizer *)pinch { //設置imageview的形變 self.imageView.transform = CGAffineTransformScale(self.imageView.transform, pinch.scale, pinch.scale); //復位 pinch.scale = 1; } #pragma mark - 處置長按手勢 - (void)longPress:(UILongPressGestureRecognizer *)longPress { //圖片處置完成 if (longPress.state == UIGestureRecognizerStateBegan) { //高亮後果 [UIView animateWithDuration:0.25 animations:^{ self.imageView.alpha = 0; } completion:^(BOOL finished) { [UIView animateWithDuration:0.25 animations:^{ self.imageView.alpha = 1; } completion:^(BOOL finished) { //高亮時生成一張新的圖片 //開啟位圖高低文 UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 0); //獲得位圖高低文 CGContextRef ctx = UIGraphicsGetCurrentContext(); //把控件的圖層襯著到高低文 [self.layer renderInContext:ctx]; //從高低文中獲得新的圖片 UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); //封閉高低文 UIGraphicsEndImageContext(); //挪用block if(_handleCompletionBlock) { _handleCompletionBlock(image); } //移除父控件 [self removeFromSuperview]; }]; }]; } } #pragma mark - 手勢署理辦法 <UIGestureRecognizerDelegate> - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { //yes表現同時支撐多個手勢 return YES; } - (void)setImage:(UIImage *)image { _image = image; //把圖片展現到UIImageView上 self.imageView.image = image; } @end
須要留意的是,當長按將操作過的圖片繪制都畫板上生成一張新的圖片後,這時候候須要把這個image設置給畫板drawView,然則這時候候就必需要在專門處置圖片的view中去import畫板view,如許耦合性太強。所認為懂得耦,可使用署理或許Block。我用了Block將方才生成的image先保留起來,在掌握器中初始化imageHandleView以後再賦值給drawView。
最初保留畫板上的內容就是將畫板上的內容生成圖片保留到相冊便可。留意,保留完以後履行的辦法必需是這個:
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo;
最初後果圖是如許的:
以上就是本文的全體內容,願望對年夜家進修IOS法式設計有所贊助。
【iOS簡略畫板開辟案例分享】的相關資料介紹到這裡,希望對您有所幫助! 提示:不會對讀者因本文所帶來的任何損失負責。如果您支持就請把本站添加至收藏夾哦!