IOS實(shí)現(xiàn)的簡(jiǎn)單畫(huà)板功能
效果圖
設(shè)計(jì)要求
1、畫(huà)筆能設(shè)置大小、顏色
2、有清屏、撤銷(xiāo)、橡皮擦、導(dǎo)入照片功能
3、能將繪好的畫(huà)面保存到相冊(cè)
實(shí)現(xiàn)思路
1、畫(huà)筆的實(shí)現(xiàn),我們可以通過(guò)監(jiān)聽(tīng)用戶(hù)的 平移手勢(shì) 中創(chuàng)建 UIBezierPath 來(lái)實(shí)現(xiàn)線(xiàn)條的繪制
2、撤銷(xiāo)功能,我們先來(lái)看下撤銷(xiāo)功能,我們會(huì)想到用一個(gè)數(shù)組隊(duì)列將用戶(hù)的每一次的筆畫(huà)都加入到數(shù)組中,然后撤銷(xiāo)的時(shí)候只需要將最后添加進(jìn)去的筆畫(huà)pop掉,重新繪制就可以了
3、清屏功能就簡(jiǎn)單了,只需要將上面說(shuō)到的那個(gè)數(shù)組清空重新繪制下就可以了
4、導(dǎo)入照片功能,可以用系統(tǒng)的 UIImagePickerController 選取照片得到UIImage,然后再將 UIImage 繪制到屏幕中就可以了
5、保存到相冊(cè)功能,可以使用 UIGraphicsGetImageFromCurrentImageContext 獲取當(dāng)前的圖片上下文,得到屏幕畫(huà)面的 UIImage ,然后通過(guò) UIImageWriteToSavedPhotosAlbum 寫(xiě)入到相冊(cè)
具體代碼實(shí)現(xiàn)
1、先畫(huà)個(gè)界面
2、因?yàn)槲覀兝L制線(xiàn)條會(huì)用到 UIBezierPath ,并且要能可設(shè)置顏色,但是UIBezierPath是沒(méi)有設(shè)置顏色的屬性,所以我們這里需要簡(jiǎn)單擴(kuò)展一下,創(chuàng)建一個(gè)繼承于 UIBezierPath 的子類(lèi) DrawPath
// // DrawPath.h // 畫(huà)板 // // Created by xgao on 16/4/13. // Copyright © 2016年 xgao. All rights reserved. // #import <UIKit/UIKit.h> @interface DrawPath : UIBezierPath // 畫(huà)筆顏色 @property(nonatomic,retain)UIColor* pathColor; @end
這個(gè)子類(lèi)只需要擴(kuò)展一個(gè)屬性,就是 pathColor 用來(lái)保存畫(huà)筆的顏色
// // DrawPath.m // 畫(huà)板 // // Created by xgao on 16/4/13. // Copyright © 2016年 xgao. All rights reserved. // #import "DrawPath.h" @implementation DrawPath @end
DrawPath.m 里面不需要做其它功能
3、接到來(lái)我們對(duì)畫(huà)板功能的實(shí)現(xiàn)封裝一下,創(chuàng)建一個(gè)繼承于UIView的 DrawView子類(lèi)
// // DrawView.h // 畫(huà)板 // // Created by xgao on 16/4/13. // Copyright © 2016年 xgao. All rights reserved. // #import <UIKit/UIKit.h> @interface DrawView : UIView // 畫(huà)線(xiàn)的寬度 @property(nonatomic,assign)CGFloat lineWidth; // 線(xiàn)條顏色 @property(nonatomic,retain)UIColor* pathColor; // 加載背景圖片 @property(nonatomic,strong)UIImage* image; // 清屏 - (void)clear; // 撤銷(xiāo) - (void)undo; // 橡皮擦 - (void)eraser; // 保存 - (void)save; @end
// // DrawView.m // 畫(huà)板 // // Created by xgao on 16/4/13. // Copyright © 2016年 xgao. All rights reserved. // #import "DrawView.h" #import "DrawPath.h" @interface DrawView() @property(nonatomic,strong) DrawPath* path; // 線(xiàn)的數(shù)組 @property(nonatomic,strong) NSMutableArray* paths; @end @implementation DrawView - (void)awakeFromNib{ [self setUp]; } - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { [self setUp]; } return self; } // 重繪UI - (void)drawRect:(CGRect)rect { for (DrawPath* path in self.paths) { if ([path isKindOfClass:[UIImage class]]) { // 畫(huà)圖片 UIImage* image = (UIImage*)path; [image drawInRect:rect]; }else{ // 畫(huà)線(xiàn) // 設(shè)置畫(huà)筆顏色 [path.pathColor set]; // 繪制 [path stroke]; } } } // 懶加載屬性 - (NSMutableArray*)paths{ if (_paths == nil) { _paths = [NSMutableArray array]; } return _paths; } // 重寫(xiě)image屬性 - (void)setImage:(UIImage *)image{ _image = image; // 將圖片加入到線(xiàn)條數(shù)組中 [self.paths addObject:image]; [self setNeedsDisplay]; } #pragma mark - Init // 初始化 - (void)setUp{ // 添加平移手勢(shì) UIPanGestureRecognizer* panGes = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(panGes:)]; [self addGestureRecognizer:panGes]; // 默認(rèn)值 self.lineWidth = 1; self.pathColor = [UIColor blackColor]; } #pragma mark - Event // 平移事件 - (void)panGes:(UIPanGestureRecognizer*)ges{ // 獲取當(dāng)前點(diǎn) CGPoint curPoint = [ges locationInView:self]; if (ges.state == UIGestureRecognizerStateBegan) { // 開(kāi)始移動(dòng) // 創(chuàng)建貝塞爾曲線(xiàn) _path = [[DrawPath alloc]init]; // 設(shè)置線(xiàn)條寬度 _path.lineWidth = _lineWidth; // 線(xiàn)條默認(rèn)顏色 _path.pathColor = _pathColor; // 設(shè)置起始點(diǎn) [_path moveToPoint:curPoint]; [self.paths addObject:_path]; } // 連線(xiàn) [_path addLineToPoint:curPoint]; // 重繪 [self setNeedsDisplay]; } #pragma mark - Method // 清屏 - (void)clear{ [self.paths removeAllObjects]; [self setNeedsDisplay]; } // 撤銷(xiāo) - (void)undo{ [self.paths removeLastObject]; [self setNeedsDisplay]; } // 橡皮擦 - (void)eraser{ self.pathColor = [UIColor whiteColor]; [self setNeedsDisplay]; } // 保存 - (void)save{ // ---- 截圖操作 // 開(kāi)啟上下文 UIGraphicsBeginImageContextWithOptions(self.frame.size, NO, 0); // 獲取當(dāng)前上下文 CGContextRef context = UIGraphicsGetCurrentContext(); // 渲染圖層到上下文 [self.layer renderInContext:context]; // 從上下文中獲取圖片 UIImage* image = UIGraphicsGetImageFromCurrentImageContext(); // 關(guān)閉上下文 UIGraphicsEndImageContext(); // ---- 保存圖片 UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil); } // 圖片保存方法,必需寫(xiě)這個(gè)方法體,不能會(huì)保存不了圖片 - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo{ // 提示 UIAlertView* alert = [[UIAlertView alloc]initWithTitle:@"保存成功" message:nil delegate:nil cancelButtonTitle:@"ok" otherButtonTitles:nil, nil]; [alert show]; } @end
4、接下來(lái)就是如果使用這個(gè)畫(huà)板類(lèi)了,直接上代碼吧
// // ViewController.m // 畫(huà)板 // // Created by xgao on 16/4/13. // Copyright © 2016年 xgao. All rights reserved. // #import "ViewController.h" #import "DrawView.h" @interface ViewController ()<UIImagePickerControllerDelegate,UINavigationControllerDelegate> // 畫(huà)板 @property (weak, nonatomic) IBOutlet DrawView *drawView; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; } #pragma mark - Event // 線(xiàn)條寬度變化 - (IBAction)lineWidthChange:(UISlider*)sender { _drawView.lineWidth = sender.value; } // 線(xiàn)條顏色變化 - (IBAction)pathColorChange:(UIButton*)sender { _drawView.pathColor = sender.backgroundColor; } // 清屏 - (IBAction)clearAction:(id)sender { [_drawView clear]; } // 撤銷(xiāo) - (IBAction)undoAction:(id)sender { [_drawView undo]; } // 橡皮擦 - (IBAction)eraserAction:(id)sender { [_drawView eraser]; } // 照片 - (IBAction)pickerPhotoAction:(id)sender { // 照片選擇控制器 UIImagePickerController* picVC = [[UIImagePickerController alloc]init]; // 照片源 picVC.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; // 委托 picVC.delegate = self; [self presentViewController:picVC animated:YES completion:nil]; } // 保存 - (IBAction)saveAction:(id)sender { [_drawView save]; } #pragma mark - UIImagePickerControllerDelegate - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)image editingInfo:(nullable NSDictionary<NSString *,id> *)editingInfo{ // 設(shè)置圖片 _drawView.image = image; // 關(guān)閉窗口 [self dismissViewControllerAnimated:YES completion:nil]; } @end
到這里就差不多了,這個(gè)小功能實(shí)現(xiàn)的基本思路與具體代碼我都已經(jīng)放上來(lái)了,大家如果還有哪里不清楚的可以留言喔~~
以上就是本文的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,同時(shí)也希望多多支持腳本之家!
相關(guān)文章
IOS開(kāi)發(fā)實(shí)現(xiàn)錄音功能
本文給大家分享的是一個(gè)IOS開(kāi)發(fā)中實(shí)現(xiàn)錄音功能的實(shí)例,并簡(jiǎn)單給大家解析一下,有需要的小伙伴可以參考下2016-03-03IOS 中NSUserDefaults讀取和寫(xiě)入自定義對(duì)象的實(shí)現(xiàn)方法
這篇文章主要介紹了IOS 中NSUserDefaults讀取和寫(xiě)入自定義對(duì)象的實(shí)現(xiàn)方法的相關(guān)資料,希望通過(guò)本文大家能夠理解掌握這部分內(nèi)容,需要的朋友可以參考下2017-09-09ios開(kāi)發(fā)加載webview顯示進(jìn)度條實(shí)例
本篇文章主要介紹了ios開(kāi)發(fā)加載webview顯示進(jìn)度條實(shí)例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-05-05iOS block循環(huán)引用詳解及常見(jiàn)誤區(qū)
這篇文章主要介紹了iOS block循環(huán)引用詳解和應(yīng)用,常見(jiàn)誤區(qū)詳解,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2021-08-08iOS 動(dòng)畫(huà) —— 禮花效果實(shí)例詳細(xì)
這篇文章主要介紹了iOS 動(dòng)畫(huà) —— 禮花效果實(shí)例詳細(xì)的相關(guān)資料,需要的朋友可以參考下2016-09-09