iOS_24_画画板(含取色板)
終于效果例如以下:
一、簡單說明1、使用一個數組 strokesArr(筆畫數組)記錄全部筆畫。數組中保存的是一個個的筆畫字典,一個字典就是一個筆畫。筆畫字典中有三項:筆畫的大小、顏色、pointsArrInOneStroke數組,(保存的是touch begin時的落筆點和touch move過程中經過的點)2、繪制的時候,從strokesArr(筆畫數組)里取出每個字典(一個字典就是一個筆畫)。依據字典中筆畫的大小、顏色、筆畫所經過的點坐標(pointsArrInOneStroke數組)。使用UIBezierPath類完畢筆畫繪制二、撤銷和回撤一個筆畫就是一個字典。 撤銷:使用abandonedStrokesArr (被丟棄的筆畫數組)保存要撤銷的筆畫,即全部筆畫數組中的最后一劃,同一時候將 strokesArr 筆畫數組中的最后一個元素刪除。反之,重做:即將abandonedStrokesArr (被丟棄的筆畫數組)中最后一個元素加入到全部筆畫數組中,同一時候將(被丟棄的筆畫數組)中的最后一個元素刪除。
Main.storyboard
主控制器
Canvas類封裝了畫畫的全部核心代碼
方法列表
撤銷: 使用abandonedStrokesArr (被丟棄的筆畫數組)保存要撤銷的筆畫。即全部筆畫數組中的最后一劃, 同一時候將 strokesArr 筆畫數組中的最后一個元素刪除。 反之。重做: 即將abandonedStrokesArr (被丟棄的筆畫數組)中最后一個元素加入到全部筆畫數組中,同一時候將(被丟棄的筆畫數組)中的最后一個元素刪除。 */ #import <UIKit/UIKit.h> // 自己定義的顏色選擇控制器,點擊之后,它會告訴代理,選中了什么顏色 @class ColorPickerController; @interface Canvas : UIView #pragma mark - 屬性列表 // 標簽,顯示筆刷大小 @property (nonatomic,retain) IBOutlet UILabel *labelSize; // 滑塊 筆刷大小 @property (nonatomic,retain) IBOutlet UISlider *sliderSize; // 三個button,各自是撤銷、重做、清除 @property (nonatomic,retain) IBOutlet UIBarButtonItem *undoBtn; @property (nonatomic,retain) IBOutlet UIBarButtonItem *redoBtn; @property (nonatomic,retain) IBOutlet UIBarButtonItem *clearBtn; // toolBar,目的是截圖的時候,隱藏掉toolBar @property (nonatomic,retain) IBOutlet UIToolbar *toolBar; #pragma mark - 方法列表 // 初始化全部的準備工作 -(void) viewJustLoaded; // 選擇相冊 被點擊 -(IBAction) didClickChoosePhoto; // 滑塊滑動,設置筆刷大小 -(IBAction) setBrushSize:(UISlider*)sender; // 撤銷 被點擊 -(IBAction) undo; // 重做 被點擊 -(IBAction) redo; // 清除畫布 被點擊 -(IBAction) clearCanvas; // 保存圖片 被點擊 -(IBAction) savePic; // 顏色選擇 被點擊 - (IBAction) didClickColorButton; // 重要~~開放給還有一個控制器調用,它在調用代理時,會傳入參數:即選擇好的顏色 - (void) pickedColor:(UIColor*)color; @end
核心代碼
// // Canvas.h // 24_Canvas畫畫板 // // Created by beyond on 14-8-26. // Copyright (c) 2014年 com.beyond. All rights reserved. /*這兒僅僅是做演示demo。直接讓Canvas與控制器綁定,開始畫畫,監聽事件假設,要更好的抽取出來,則須要創建一個模型類(model)來提供數據源(比方_strokesArr,_abandonedStrokesArr),供CanvasView顯示UIView的setNeedsDisplay和setNeedsLayout方法首先兩個方法都是異步運行的。
而setNeedsDisplay會調用自己主動調用drawRect方法,這樣能夠拿到 UIGraphicsGetCurrentContext。就能夠畫畫了。
UIUserInterfaceIdiomPad iPad上專用 */ #import "Canvas.h" #import "ColorPickerController.h" #import "BeyondViewController.h" @interface Canvas ()<UIImagePickerControllerDelegate,UINavigationControllerDelegate> { // 全部筆畫 NSMutableArray *_strokesArr; // 丟棄(撤銷)的筆畫 NSMutableArray *_abandonedStrokesArr; // 當前筆刷顏色 UIColor *_currentColor; // 當前的筆刷大小 float currentSize; // 選中的圖片 UIImage *_pickedImg; // 截屏圖片 UIImage *_screenImg; // 自己定義的 顏色選擇控制器 ColorPickerController *_colorPickerCtrl; // 相片選擇器 UIImagePickerController *_imagePickerCtrl; } @end @implementation Canvas #pragma mark - 生命周期方法 // 禁止多點觸摸 -(BOOL)isMultipleTouchEnabled { return NO; } // 最重要的繪圖方法 - (void) drawRect: (CGRect) rect { // 1.先把獲取的圖片,畫到畫布上 [self drawPickedImgToCanvas]; // 2.假設【筆畫數組】有筆畫字典,則按順序將筆畫取出,畫到畫布上 [self drawStrokesArrToCanvas]; } // 1.先把獲取的圖片,畫到畫布上 - (void)drawPickedImgToCanvas { int width = _pickedImg.size.width; int height = _pickedImg.size.height; CGRect rectForImage = CGRectMake(0, 0, width, height); [_pickedImg drawInRect:rectForImage]; } // 2.假設【筆畫數組】有筆畫字典,則按順序將筆畫取出,畫到畫布上 - (void)drawStrokesArrToCanvas { // 假設【筆畫數組】為空,則直接返回 if (_strokesArr.count == 0) return; // 遍歷【筆畫數組】,取出每個筆畫字典,每一次迭代,畫一個stroke for (NSDictionary *oneStrokeDict in _strokesArr) { // 取出點數組 NSArray *pointsArr = [oneStrokeDict objectForKey:@"points"]; // 取出顏色 UIColor *color = [oneStrokeDict objectForKey:@"color"]; // 取出筆刷尺寸 float size = [[oneStrokeDict objectForKey:@"size"] floatValue]; // 設置顏色 [color set]; // line segments within a single stroke (path) has the same color and line width // 畫一個stroke, 一條接著一條,使用圓接頭 round joint // 創建一個貝塞爾路徑 UIBezierPath* bezierPath = [UIBezierPath bezierPath]; // 點數組 中的第一個,就是 起點 CGPoint startPoint = CGPointFromString([pointsArr objectAtIndex:0]); // 將路徑移動到 起點 [bezierPath moveToPoint:startPoint]; // 遍歷點數組,將每個點,依次加入到 bezierPath for (int i = 0; i < (pointsArr.count - 1); i++) { // 依次取出下一個點 CGPoint pointNext = CGPointFromString([pointsArr objectAtIndex:i+1]); // 加入到路徑 [bezierPath addLineToPoint:pointNext]; } // 設置線寬 bezierPath.lineWidth = size; // 線連接處為 圓結頭 bezierPath.lineJoinStyle = kCGLineJoinRound; // 線兩端為 圓角 bezierPath.lineCapStyle = kCGLineCapRound; // 調用路徑的方法 畫出一條線 [bezierPath stroke]; } } // 重要~~~初始化全部東東 -(void) viewJustLoaded { // 1.初始化顏色選擇控制器 [self addColorPickerCtrl]; // 2.初始化【相片選擇器】 [self addUIImagePickerCtrl]; // 3.其它成員初始化 // 【筆畫數組】 _strokesArr = [NSMutableArray array]; // 【被丟棄的筆畫數組】 _abandonedStrokesArr = [NSMutableArray array]; // 筆畫大小 currentSize = 5.0; // toolBar上筆畫標簽顯示文字 self.labelSize.text = @"Size: 5"; // 設置筆刷 黑色 [self setStrokeColor:[UIColor blackColor]]; // 4.設置重做、撤銷、清空三個button的狀態 [self updateToolBarBtnStatus]; } // 1.初始化顏色選擇控制器 - (void)addColorPickerCtrl { // 1.加入【顏色選擇控制器】ColorPickerController。由于要加入到主控制器中 BeyondViewController *mainVC = [BeyondViewController sharedBeyondViewController]; // 初始化自己封裝的顏色選擇控制器,并設置好代理,目的是顏色設置好了之后,回調告訴當前的canvas畫布 _colorPickerCtrl = [[ColorPickerController alloc] init]; _colorPickerCtrl.pickedColorDelegate = self; // 控制器成為父子關系,視圖也成為父子關系 [mainVC addChildViewController:_colorPickerCtrl]; [mainVC.view addSubview:_colorPickerCtrl.view]; // 臨時隱藏【顏色選擇控制器】,僅僅有在點擊了ToolBar上面的button時候,才顯示出來 _colorPickerCtrl.view.hidden = YES; } // 2.初始化【相片選擇器】 - (void)addUIImagePickerCtrl { if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) { _imagePickerCtrl = [[UIImagePickerController alloc] init]; _imagePickerCtrl.delegate = self; _imagePickerCtrl.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; // 2) 設置同意改動 // [_imagePickerCtrl setAllowsEditing:YES]; } } // 3.自己定義方法,設置 撤銷、重做、清空三個button的可點擊狀態 - (void)updateToolBarBtnStatus { _redoBtn.enabled = _abandonedStrokesArr.count > 0; _undoBtn.enabled = _strokesArr.count > 0; _clearBtn.enabled = _strokesArr.count > 0; } #pragma mark - 控件連線方法 // 滑塊滑動 - (IBAction)setBrushSize:(UISlider*)sender { currentSize = sender.value; self.labelSize.text = [NSString stringWithFormat:@"Size: %.0f",sender.value]; } // 撤銷button點擊事件 -(IBAction) undo { // 假設筆畫數組中有筆畫字典 if ([_strokesArr count]>0) { // 最后一個筆畫字典,即,被丟棄的筆畫字典 NSMutableDictionary* abandonedStrokeDict = [_strokesArr lastObject]; // 將最后一個筆畫字典,加入到被丟棄的筆畫字典數組里面保存,以供drawRect [_abandonedStrokesArr addObject:abandonedStrokeDict]; // 從全部筆畫數組中移除掉最后一筆 [_strokesArr removeLastObject]; // 又一次調用drawRect進行繪制 [self setNeedsDisplay]; } // 2.設置重做、撤銷、清空三個button的狀態 [self updateToolBarBtnStatus]; } // 重做 -(IBAction) redo { // 假設 被丟棄的筆畫數組,里面有值 if ([_abandonedStrokesArr count]>0) { // 取出最后一個被仍進來的 筆畫字典,(即最先書寫的,并且是在撤銷的操作里面,最后被加入到【被丟棄的筆畫數組】) NSMutableDictionary* redoStrokeDict = [_abandonedStrokesArr lastObject]; // 將須要重畫的筆畫字典,加入到【全部筆畫數組】中 [_strokesArr addObject:redoStrokeDict]; // 并且,從【被丟棄的筆畫數組】中移除,該筆畫字典 [_abandonedStrokesArr removeLastObject]; // 又一次調用drawRect進行繪制 [self setNeedsDisplay]; } // 2.設置重做、撤銷、清空三個button的狀態 [self updateToolBarBtnStatus]; } // 清空畫布,僅僅需清空【全部筆畫數組】和【被丟棄的筆畫數組】 -(IBAction) clearCanvas { // 建議不要將選擇出來的背景圖片清空,僅僅清空沒寫好的筆畫算了 // _pickedImg = nil; [_strokesArr removeAllObjects]; [_abandonedStrokesArr removeAllObjects]; // 又一次調用drawRect進行繪制 [self setNeedsDisplay]; // 2.設置重做、撤銷、清空三個button的狀態 [self updateToolBarBtnStatus]; } // 保存圖片 -(IBAction) savePic { // 臨時移除 工具條 //[_toolBar removeFromSuperview]; // 截圖代碼 // 1,開啟上下文 UIGraphicsBeginImageContext(self.bounds.size); // 2.將圖層渲染到上下文 [self.layer renderInContext:UIGraphicsGetCurrentContext()]; // 開啟上下文,使用參數之后,截出來的是原圖(YES 0.0 質量高) //UIGraphicsBeginImageContextWithOptions(self.frame.size, YES, 0.0); // 3.從上下文中取出圖片 _screenImg = UIGraphicsGetImageFromCurrentImageContext(); // 4.關閉上下文 UIGraphicsEndImageContext(); // 又一次加入 工具條,并置最上方 //[self addSubview:_toolBar]; //[self bringSubviewToFront:self.labelSize]; // 調用自己定義方法,保存截屏到相冊 [self performSelector:@selector(saveToPhoto) withObject:nil afterDelay:0.0]; } // 自己定義方法,保存截屏到相冊 -(void) saveToPhoto { // 一句話,寫到相冊 UIImageWriteToSavedPhotosAlbum(_screenImg, nil, nil, nil); // UIAlertView 提示成功 UIAlertView* alertView= [[UIAlertView alloc] initWithTitle:nil message:@"Image Saved" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alertView show]; } // 點擊選擇顏色button - (IBAction) didClickColorButton { // 顯示或隱藏 自己的【顏色選擇控制器】 _colorPickerCtrl.view.hidden = !_colorPickerCtrl.view.hidden; } // 當_colorPickerCtrl選擇顏色完成,會調用代理 的本方法 - (void) pickedColor:(UIColor*)color { // 將【顏色選擇控制器】,回調的顏色,設置到控件上,并隱藏 【顏色選擇控制器】 [self setStrokeColor:color]; _colorPickerCtrl.view.hidden = !_colorPickerCtrl.view.hidden; } // 重要,設置筆刷 新的顏色 -(void) setStrokeColor:(UIColor*)newColor { _currentColor = newColor; } // 點擊,選擇相片button -(IBAction) didClickChoosePhoto { // 展現,相片選擇控制器 [self addSubview:_imagePickerCtrl.view]; } #pragma mark - imagePicker代理方法 - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { // 必須手動,關閉照片選擇器 [picker.view removeFromSuperview]; // 從info字典得到編輯后的照片【UIImagePickerControllerEditedImage】 _pickedImg = [info valueForKey:@"UIImagePickerControllerOriginalImage"]; // 將圖片畫到畫板上去 [self setNeedsDisplay]; } // 【相片選擇器】的代理方法,點擊取消時,也要隱藏相片選擇器 - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker { [_imagePickerCtrl.view removeFromSuperview]; } #pragma mark - 核心代碼,重要~~~畫布上手勢處理 // 手勢開始(畫筆落下) // 開始一個新的字典,為每一筆,包含點 和 顏色 // Start new dictionary for each touch, with points and color - (void) touchesBegan:(NSSet *) touches withEvent:(UIEvent *) event { // 一個筆畫中的全部點,觸摸開始時的【起點】 NSMutableArray *pointsArrInOneStroke = [NSMutableArray array]; NSMutableDictionary *strokeDict = [NSMutableDictionary dictionary]; [strokeDict setObject:pointsArrInOneStroke forKey:@"points"]; // 筆的顏色 [strokeDict setObject:_currentColor forKey:@"color"]; // 筆的大小 [strokeDict setObject:[NSNumber numberWithFloat:currentSize] forKey:@"size"]; // 落筆點 CGPoint point = [[touches anyObject] locationInView:self]; [pointsArrInOneStroke addObject:NSStringFromCGPoint(point)]; [_strokesArr addObject:strokeDict]; } // 將每個點加入到 點數組 // Add each point to points array - (void) touchesMoved:(NSSet *) touches withEvent:(UIEvent *) event { // 移動后的一個點 CGPoint point = [[touches anyObject] locationInView:self]; // 前一個點 CGPoint prevPoint = [[touches anyObject] previousLocationInView:self]; // 字典中先前的點數組 NSMutableArray *pointsArrInOneStroke = [[_strokesArr lastObject] objectForKey:@"points"]; // 在后面追加 新的點 [pointsArrInOneStroke addObject:NSStringFromCGPoint(point)]; CGRect rectToRedraw = CGRectMake(\ ((prevPoint.x>point.x)?point.x:prevPoint.x)-currentSize,\ ((prevPoint.y>point.y)?point.y:prevPoint.y)-currentSize,\ fabs(point.x-prevPoint.x)+2*currentSize,\ fabs(point.y-prevPoint.y)+2*currentSize\ ); [self setNeedsDisplayInRect:rectToRedraw]; } // 手勢結束(畫筆抬起) // Send over new trace when the touch ends - (void) touchesEnded:(NSSet *) touches withEvent:(UIEvent *) event { [_abandonedStrokesArr removeAllObjects]; // 2.設置重做、撤銷、清空三個button的狀態 [self updateToolBarBtnStatus]; } @end
顏色選擇控制器
ColorPickerController
核心代碼
總結
以上是生活随笔為你收集整理的iOS_24_画画板(含取色板)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux下装完mysql后默认密码是多
- 下一篇: R语言心得-分词包的安装