考虑到公司业务需求,要做一个客户签约功能,可能会用到一个手动签名的视图,就自己封装了一个简单的视图控件,造个轮子。
实现思路:
先思考一个问题:一个签名视图都需要哪些材料与功能?
首先是原材料:画板和画笔(由于是用于签名,画板不做定制了,只考虑画笔就行了,预留一个画板--可以添加个背景图片(backgroundImage))。
画笔有哪些属性呢?画笔颜色(lineColor)和粗细(lineWidth)。
@property (nonatomic, strong) UIColor *lineColor; //画笔颜色 @property (nonatomic, assign) CGFloat lineWidth; //画笔宽度 @property (nonatomic, strong) UIImage *backgroundImage; //背景图片
原材料确定了,接下来就是功能了,也就是要造什么样的轮子。
首先是要画,有路径轨迹,画好后能获取到这个签名视图,可以保存到相册,这是基础功能。
附加功能有,既然签名,就有可能写错,或者不好看,那么就需要清除操作功能,如果不想把之前的操作都清除,需要一步一步撤销,那么就需要添加个单步撤销操作功能,如果后悔了,可能需要反撤销。
/** 获取签名图片 @return 签名Image */ - (UIImage *)signatureImage; /** 撤销上一步绘制 */ - (void)undoLastDraw; /** 恢复上次撤销操作 */ - (void)redoLastDraw; /** 清除所有操作 */ - (void)clearSignature; /** 保存签名 */ - (void)saveSignature;
原材料和功能确定好了,接下来就是怎么生产“轮子”了。
设置巴塞尔曲线的特性
- (UIBezierPath *)bezierPath { if (!_bezierPath) { _bezierPath = [UIBezierPath bezierPath]; _bezierPath.lineJoinStyle = kCGLineJoinRound; _bezierPath.lineCapStyle = kCGLineCapRound; _bezierPath.lineWidth = _lineWidth; } return _bezierPath; }
创建画笔操作数组
- (NSMutableArray *)pathsArray { if (!_pathsArray) { _pathsArray = [NSMutableArray arrayWithCapacity:1]; } return _pathsArray; } - (NSMutableArray *)backPathsArray { if (!_backPathsArray) { _backPathsArray = [NSMutableArray arrayWithCapacity:1]; } return _backPathsArray; }
开始绘制
#pragma mark - Touches Action - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches allObjects].lastObject; CGPoint startPoint = [touch locationInView:self]; [self.bezierPath moveToPoint:startPoint]; [self.pathsArray addObject:self.bezierPath]; [self.backPathsArray removeAllObjects]; } - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches allObjects].lastObject; CGPoint touchPoint = [touch locationInView:self]; [self.bezierPath addLineToPoint:touchPoint]; [self setNeedsDisplay]; } - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { self.bezierPath = nil; }
功能操作:
#pragma mark - Public Actions #pragma mark - 撤销上步绘制操作 - (void)undoLastDraw { if (self.pathsArray.count >0) { NSInteger index = self.pathsArray.count - 1; [self.backPathsArray addObject:self.pathsArray[index]]; [self.pathsArray removeObjectAtIndex:index]; [self setNeedsDisplay]; } } #pragma mark - 恢复上步撤销的d操作 - (void)redoLastDraw { if (self.backPathsArray.count >0) { NSInteger index = self.backPathsArray.count - 1; [self.pathsArray addObject:self.backPathsArray[index]]; [self.backPathsArray removeObjectAtIndex:index]; [self setNeedsDisplay]; } } #pragma mark - 清空所有操作 - (void)clearSignature { [self.pathsArray removeAllObjects]; [self setNeedsDisplay]; }
获取签名视图
#pragma mark - 获取签名图片 - (UIImage *)signatureImage { UIGraphicsBeginImageContext(self.frame.size);//创建一个基于位图的上下文,并设置当前上下文 CGContextRef contex = UIGraphicsGetCurrentContext();//获取图形上下文 UIRectClip(CGRectMake(3, 15, self.frame.size.width-6, self.frame.size.height-30));//裁剪区域 [self.layer renderInContext:contex]; UIImage * image = UIGraphicsGetImageFromCurrentImageContext(); NSData* imageData = UIImagePNGRepresentation(image);//生成 PNG 格式的图片(如果是其他格式,可以自行更改) UIImage* pngImage = [UIImage imageWithData:imageData]; return pngImage; }
保存到相册
#pragma mark - 保存到相册 - (void)saveSignature { UIImage *pngImage = [self signatureImage]; UIImageWriteToSavedPhotosAlbum(pngImage, self, nil, NULL); }
签名的基础功能都实现了。