日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

iOS开发之简单画板实现

發布時間:2025/7/14 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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


#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?=?CGAffineTransformTranslate(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();//調用blockif(_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;


最后效果圖是這樣的:

畫線:? 帶圖片的:? 保存生成的圖片:

轉載于:https://my.oschina.net/shenhuniurou/blog/653929

總結

以上是生活随笔為你收集整理的iOS开发之简单画板实现的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。