一、效果圖:
二、選擇顏色:
分【固定顏色模式】和【自由取模式】。
三、操作欄功能:
1、撤銷:撤銷上一步操作,可一直往上進行,直到全部清空。
2、清空:直接清除所有繪畫。
3、橡皮擦:去除不要的繪畫部分。
4、保存:一鍵保存相冊。
四、實現方式:
貝塞爾曲線結合drawrect繪畫。
代碼結構:
核心代碼模塊:
#pragma mark - 畫畫 -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; CGPoint currentPoint = [touch locationInView:self]; self.bezierPath = [[YJBezierPath alloc] init]; self.bezierPath.lineColor = self.lineColor; self.bezierPath.isErase = self.isErase; [self.bezierPath moveToPoint:currentPoint]; [self.beziPathArrM addObject:self.bezierPath]; } -(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ UITouch *touch = [touches anyObject]; CGPoint currentPoint = [touch locationInView:self]; CGPoint previousPoint = [touch previousLocationInView:self]; CGPoint midP = midpoint(previousPoint,currentPoint); // 這樣寫不會有尖頭 [self.bezierPath addQuadCurveToPoint:currentPoint controlPoint:midP]; [self setNeedsDisplay]; } -(void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ UITouch *touch = [touches anyObject]; CGPoint currentPoint = [touch locationInView:self]; CGPoint previousPoint = [touch previousLocationInView:self]; CGPoint midP = midpoint(previousPoint,currentPoint); [self.bezierPath addQuadCurveToPoint:currentPoint controlPoint:midP]; // touchesMoved [self setNeedsDisplay]; }
-(void)drawRect:(CGRect)rect{ if (self.beziPathArrM.count) { for (YJBezierPath *path in self.beziPathArrM) { if (path.isErase) { [self.backgroundColor setStroke]; }else{ [path.lineColor setStroke]; } path.lineCapStyle = kCGLineCapRound; path.lineJoinStyle = kCGLineCapRound; if (path.isErase) { path.lineWidth = 10; // 這里可抽取出來枚舉定義 [path strokeWithBlendMode:kCGBlendModeDestinationIn alpha:1.0]; }else{ path.lineWidth = 3; [path strokeWithBlendMode:kCGBlendModeNormal alpha:1.0]; } [path stroke]; } } [super drawRect:rect]; }
外部引用代碼:
#import "BaiBanViewController.h" #import "BaibanView.h" @interface BaiBanViewController () @property (nonatomic,strong) BaibanView *baibanV; @end @implementation BaiBanViewController -(BaibanView *)baibanV{ if(_baibanV==nil){ _baibanV=[[BaibanView alloc] initWithFrame:CGRectMake(0, 64, KScreenWidth, KScreenHeight - 64)]; } return _baibanV; } - (void)viewDidLoad { [super viewDidLoad]; self.navigationItem.title = @"畫 板"; [[UIBarButtonItem appearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(0, -60) forBarMetrics:UIBarMetricsDefault]; self.view.backgroundColor = [UIColor whiteColor]; //添加畫板功能 [self.view addSubview:self.baibanV]; }
簡單吧~
五、源碼獲取:
我直接把我的測試Demo放上去了,大家下載后,直接定位畫板功能即可。
========================更新於2017年==========================
上面那種方式,是利用drawrect方式繪畫,通過cpu渲染,所以一定程度上比較耗cpu,內存也有一定上升
因此,如果你的應用不需要橡皮擦功能,只需要上一步或下一步這種的撤銷操作,可以利用CAShapeLayer集合來實現,原理如下:
每一筆都是一個layer,然后一層層疊加在底view上,並記錄到一個list里,這樣,上一步和下一步都是直接對一個layer進行add或remove,簡單明了,而且這種對於,繪畫特殊圖形也比較方便(比如畫圓、矩形等)
下圖是我另一個應用的塗鴉功能截圖,這種對內存和cpu消耗特別低,而且集成了縮放、旋轉功能, 大家可以借鑒一下。
但這種實現,如果需要橡皮擦功能,只能實現橡皮擦擦除區域與layer有交匯點,就清除layer(類似蘋果相冊編輯里的橡皮擦功能),如果想實現任意清除, 我暫時沒想到特別好的解決方式。