iOS开发之简单画板实现
2019獨角獸企業重金招聘Python工程師標準>>>
這幾天在學習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;@end -?(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?addLineToPoint: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];//創建一個處理圖片的viewImageHandleView?*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需要注意的是,當長按將操作過的圖片繪制都畫板上生成一張新的圖片后,這時候需要把這個image設置給畫板drawView,但是這時候就必須要在專門處理圖片的view中去import畫板view,這樣耦合性太強。所以為了解耦,可以使用代理或者Block。我用了Block將剛剛生成的image先保存起來,在控制器中初始化imageHandleView之后再賦值給drawView。
最后保存畫板上的內容就是將畫板上的內容生成圖片保存到相冊即可。注意,保存完之后執行的方法必須是這個:
-?(void)image:(UIImage?*)image?didFinishSavingWithError:(NSError?*)error?contextInfo:(void?*)contextInfo;最后效果圖是這樣的:
畫線:? 帶圖片的:? 保存生成的圖片:
轉載于:https://my.oschina.net/shenhuniurou/blog/653929
總結
以上是生活随笔為你收集整理的iOS开发之简单画板实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python操作mongo(2)
- 下一篇: 无密码身份验证:安全、简单且部署快速