美文网首页
iOS 手写签名并生成图片

iOS 手写签名并生成图片

作者: CJ_BLUE | 来源:发表于2017-08-18 13:27 被阅读0次
    简介

    由于项目需求,安卓的同事做了这样一个功能,iOS不用做,我还是找了找资料,做了一个小dome,GitHub地址,进入正题。

    1.封装一个view作为签名视图,属性很好懂,就是设置签名的线的颜色,线宽,还有最后生成的图片,以及图片的缩放比例,方法分别是准备开始画线,重置以及保存
    #import <UIKit/UIKit.h>
    
    @interface CJSignatureView : UIView
    // 线宽 默认1
    @property (nonatomic, assign) CGFloat lineWidth;
    // 线颜色 默认黑
    @property (nonatomic, strong) UIColor *lineColor;
    // 生成图片的缩放比例 默认1不缩放 范围0.1~1.0
    @property (nonatomic, assign) CGFloat imageScale;
    // 生成的图片
    @property (nonatomic, strong) UIImage *signImage;
    
    // 初始化视图之后调用 准备画图
    - (void)startDraw;
    // 重置
    - (void)resetDraw;
    // 保存成图片
    - (void)saveDraw;
    
    @end
    
    2.初始化path
    // 先声明两个全局变量
    UIBezierPath *path;// 签名的线
    CGPoint previousPoint;// 上一个点
    
    #pragma mark 准备开始签名
    - (void)startDraw
    {
        // 背景色
        self.backgroundColor = [UIColor whiteColor];
        // 初始化 设置属性
        path = [UIBezierPath bezierPath];
        // 线宽
        path.lineWidth = _lineWidth ? _lineWidth : 1;
        // 线颜色
        if (_lineColor) {
            [_lineColor set];
        }
    }
    
    3.画线,将第一个点击的点和之后移动到的点连接
    #pragma mark 画线刚开始,保存上一个点
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
    {
        // 获取点击点坐标
        UITouch * touch = touches.anyObject;
        CGPoint currentPoint = [touch locationInView:self];
        // 保存成上一点
        previousPoint = currentPoint;
        // 开始点移动到点击点
        [path moveToPoint:currentPoint];
    }
    #pragma mark 开始画线,连接上一个点和当前点
    - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
    {
        // 获取点击点坐标
        UITouch * touch = touches.anyObject;
        CGPoint currentPoint = [touch locationInView:self];
        
        // 获取两点中点
        CGPoint midPoint = midpoint(previousPoint, currentPoint);
        // 画曲线
        [path addQuadCurveToPoint:midPoint controlPoint:previousPoint];
        // 替换当前点为上一点
        previousPoint = currentPoint;
        // 画图,调用系统的darwRect:
        [self setNeedsDisplay];
    }
    #pragma mark 系统画线方法
    - (void)drawRect:(CGRect)rect
    {
        [path stroke];
    }
    
    4.写重置方法,调用startDraw重置属性,调用setNeedsDisplay重画图(path这时候时空的)
    #pragma mark 重置path
    - (void)resetDraw
    {
        [self startDraw];
        [self setNeedsDisplay];
    }
    
    5.写保存方法,这里涉及到2个方法,截图以及缩放
    #pragma mark 保存成图片
    - (void)saveDraw
    {
        self.signImage = [self captureWithView:self];
        if (!_imageScale) {
            return;
        }
        // 这里控制范围,范围可以自己定
        if (_imageScale < 0.1) {
            _imageScale = 0.1;
        }
        if (_imageScale > 1) {
            _imageScale = 1;
        }
        if (_imageScale != 1) {
            [self scaleImage];
        }
        
    }
    
    #pragma mark 缩放图片
    - (UIImage *)scaleImage
    {
        // 用这个方法 画质会变渣 
    //    UIGraphicsBeginImageContext(CGSizeMake(_signImage.size.width * _imageScale, _signImage.size.height * _imageScale));
    //    [_signImage drawInRect:CGRectMake(0, 0, _signImage.size.width * _imageScale, _signImage.size.height * _imageScale)];
    //    self.signImage = UIGraphicsGetImageFromCurrentImageContext();
    //    UIGraphicsEndImageContext();
        
        // 判断机型
        if([[UIScreen mainScreen] scale] == 2.0){      // @2x
            UIGraphicsBeginImageContextWithOptions(CGSizeMake(_signImage.size.width * _imageScale, _signImage.size.height * _imageScale), NO, 2.0);
        }else if([[UIScreen mainScreen] scale] == 3.0){ // @3x ( iPhone 6plus 、iPhone 6s plus)
            UIGraphicsBeginImageContextWithOptions(CGSizeMake(_signImage.size.width * _imageScale, _signImage.size.height * _imageScale), NO, 3.0);
        }else{
            UIGraphicsBeginImageContext(CGSizeMake(_signImage.size.width * _imageScale, _signImage.size.height * _imageScale));
        }
        // 绘制改变大小的图片
        [_signImage drawInRect:CGRectMake(0, 0, _signImage.size.width * _imageScale, _signImage.size.height * _imageScale)];
        // 从当前context中创建一个改变大小后的图片
        _signImage = UIGraphicsGetImageFromCurrentImageContext();
        // 使当前的context出堆栈
        UIGraphicsEndImageContext();
        // 返回新的改变大小后的图片
        
        return self.signImage;
    }
    
    #pragma mark 截屏
    - (UIImage *)captureWithView:(UIView *)view
    {
        CGRect screenRect = [view bounds];
        UIGraphicsBeginImageContext(screenRect.size);
        CGContextRef ctx = UIGraphicsGetCurrentContext();
        [view.layer renderInContext:ctx];
        UIImage * image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return image;
    }
    
    
    6.调用,调用比较简单了直接上代码了,这里写的例子是A控制器跳转到B控制器,在B中签名,并把图片返回到A显示
    // A控制器.m代码
    @implementation ViewController
    {
        UIImageView *showImageView;
    }
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        self.view.backgroundColor = [UIColor cyanColor];
        
        showImageView = [[UIImageView alloc] initWithFrame:self.view.frame];
        [self.view addSubview:showImageView];
        showImageView.contentMode = UIViewContentModeScaleAspectFit;
    }
    
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
    {
        CJDrawViewController *VC = [CJDrawViewController new];
        VC.delegate = self;
        [self presentViewController:VC animated:YES completion:nil];
    }
    // 代理方法
    - (void)returnImage:(UIImage *)signImage
    {
        showImageView.frame = CGRectMake(0, 0, signImage.size.width, signImage.size.height);
        showImageView.center = self.view.center;
        showImageView.image = signImage;
    }
    
    
    // B控制器.h代码
    @protocol CJDrawViewControllerDelegate <NSObject>
    // 返回签名图片
    - (void)returnImage:(UIImage *)signImage;
    
    @end
    
    @interface CJDrawViewController : UIViewController
    
    @property (nonatomic, assign) id<CJDrawViewControllerDelegate> delegate;
    
    @end
    
    B控制器.m代码
    #import "CJDrawViewController.h"
    #import "CJSignatureView.h"
    
    @interface CJDrawViewController ()
    
    @property (nonatomic, strong) CJSignatureView *signView;
    
    @end
    
    @implementation CJDrawViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        self.view.backgroundColor = [UIColor yellowColor];
        [self.view addSubview:self.signView];
        [self createView];
    }
    #pragma mark 初始化
    - (CJSignatureView *)signView
    {
        if (!_signView) {
            _signView = [[CJSignatureView alloc] initWithFrame:CGRectMake(0, self.view.frame.size.height/2.0-200/2.0, self.view.frame.size.width, 200)];
            _signView.lineColor = [UIColor redColor];
            _signView.lineWidth = 2;
            _signView.imageScale = 0.5;
            [_signView startDraw];
        }
        return _signView;
    }
    #pragma mark 创建按钮
    - (void)createView
    {
        NSArray *titleArr = @[@"返回", @"重置", @"保存"];
        
        CGFloat btnW = self.view.frame.size.width/3.0;
        for (int i = 0; i < titleArr.count; i++) {
            UIButton *btn = [UIButton buttonWithType:UIButtonTypeSystem];
            btn.frame = CGRectMake(btnW*i, self.view.frame.size.height-40, btnW, 40);
            [self.view addSubview:btn];
            [btn setTitle:titleArr[i] forState:UIControlStateNormal];
            [btn addTarget:self action:@selector(btnAction:) forControlEvents:UIControlEventTouchUpInside];
            btn.tag = 100+i;
        }
    }
    #pragma mark 按钮点击方法
    - (void)btnAction:(UIButton *)btn
    {
        switch (btn.tag) {
            case 100:
                [self dismissViewControllerAnimated:YES completion:nil];
                break;
            case 101:
                [_signView resetDraw];
                break;
            case 102:
                [_signView saveDraw];
                if ([self.delegate respondsToSelector:@selector(returnImage:)]) {
                    [self.delegate returnImage:_signView.signImage];
                }
                [self dismissViewControllerAnimated:YES completion:nil];
                break;
                
            default:
                break;
        }
    }
    

    这样,一个简单的签名就封装好了,里面有许多的东西是可以根据具体需求修改的。

    结语:限于水平,本文只写了一些基本用法和注意事项,如果文中存在错误请指出,我会及时修改。

    相关文章

      网友评论

          本文标题:iOS 手写签名并生成图片

          本文链接:https://www.haomeiwen.com/subject/jmqarxtx.html