封装一个简单的视图--手写签名视图

  考虑到公司业务需求,要做一个客户签约功能,可能会用到一个手动签名的视图,就自己封装了一个简单的视图控件,造个轮子。

  实现思路:

  先思考一个问题:一个签名视图都需要哪些材料与功能?

  首先是原材料:画板和画笔(由于是用于签名,画板不做定制了,只考虑画笔就行了,预留一个画板--可以添加个背景图片(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);
}

  签名的基础功能都实现了。

  附上代码链接:https://github.com/zhangtibin/SignatureView

原文地址:https://www.cnblogs.com/ZachRobin/p/7760317.html