OC图片滑动验证

没事逛cocoaChina的时候有人问图片验证码怎么做,我看了下,网上有很多第三方的框架,但好多都是收费的,所以考虑自己能否做一个,该封装有点简陋,不过可以根据自己需要自行修改

该代码用到的技术,UIBezierPath可以参考我的另外一篇博客、还UIProgressView的第二次封装、还有手势,这个我之前也有写过博客,和这个大同小异

效果图:

 需要用到的代码:

 CustomProgressView是对UIProgressView的封装,可以通过拖动滑块改变进度条value值,这个地方我用的是一个UILabel,有点难看,后期可以根据自己的需要改为图片,楼主的原则是'只要能用其他的控件代替,就不用图片'

CustomProgressView.h

#import <UIKit/UIKit.h>

@interface CustomProgressView : UIView
/**
 progress的value值 isEnd是否停止滑动
 */
@property(nonatomic,copy)void(^blockProgressValue)(float value,BOOL isEnd);
-(void)setProgress:(float)progress;
@end

 CustomProgressView.m

#import "CustomProgressView.h"

@interface CustomProgressView ()
@property(nonatomic,strong)UIProgressView *preView;
@property(nonatomic,strong)UILabel *trackLab;
@end

@implementation CustomProgressView

-(instancetype)initWithFrame:(CGRect)frame{
    self = [super initWithFrame:frame];
    if(self){
        self.preView = [[UIProgressView alloc]initWithFrame:CGRectMake(0, frame.size.height/2.0, frame.size.width, 1)];
        self.preView.progressTintColor = [UIColor redColor];
        self.preView.trackTintColor = [UIColor grayColor];
        [self addSubview:self.preView];
        
        self.trackLab = [[UILabel alloc]initWithFrame:CGRectMake(0,frame.size.height/2.0-10, 20, 20)];
        self.trackLab.backgroundColor = [UIColor redColor];
        self.trackLab.userInteractionEnabled = YES;
        [self addSubview:self.trackLab];
    }
    return self;
}
-(void)setProgress:(float)progress{
    float x = self.bounds.size.width * progress;
    CGRect rect = self.trackLab.frame;
    rect.origin.x = x;
    self.trackLab.frame = rect;
    [self.preView setProgress:progress];
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
}
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    UITouch *touch = [touches anyObject];
    if([touch.view isKindOfClass:[UILabel class]]){
        CGPoint point = [touch locationInView:[touch.view superview]];
        float x = point.x;
        CGRect rect = self.trackLab.frame;
        if(x < 0 ){
            rect.origin.x = 0;
            self.trackLab.frame = rect;
            
            return;
        }
        if(x > self.bounds.size.width-20){
            rect.origin.x = self.bounds.size.width-20;
            self.trackLab.frame = rect;
            return;
        }
        rect.origin.x = x;
        self.trackLab.frame = rect;
        [self.preView setProgress:x/self.bounds.size.width];
        if(self.blockProgressValue){
            self.blockProgressValue(x/self.bounds.size.width,NO);
        }
    }
}

-(void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    UITouch *touch = [touches anyObject];
    if([touch.view isKindOfClass:[UILabel class]]){
        if(self.blockProgressValue){
            self.blockProgressValue(self.preView.progress,YES);
        }
    }
    
}


@end

 

ImageLockView.h

#import <UIKit/UIKit.h>

@interface ImageLockView : UIView
-(void)show;
-(void)hidden;
@end

 ImageLockView.m

#import "ImageLockView.h"
#import "CustomProgressView.h"
//屏幕的宽度
#define ScreenWidth  [UIScreen mainScreen].bounds.size.width
//屏幕的高度
#define ScreenHeight  [UIScreen mainScreen].bounds.size.height
//内容的宽度
#define ContentWidth 200
//内容的高度
#define ContentHeight 230
//间距
#define Margin 10
@interface ImageLockView (){
    CGRect frontRect;//
}
/**半透明背景蒙版*/
@property(nonatomic,strong)UIView *backView;
/**内容view,白的的圆角矩形*/
@property(nonatomic,strong)UIView *contentView;
/**底下一层的Img*/
@property(nonatomic,strong)UIImageView *backImg;
/**滑动Img*/
@property(nonatomic,strong)UIImageView *frontImg;
/***最下方可以滑动的ProgressView*/
@property(nonatomic,strong)CustomProgressView *progressView;
@end

@implementation ImageLockView

- (instancetype)initWithFrame:(CGRect)frame{
    frame = CGRectMake(0, 0, ScreenWidth, ScreenHeight);
    self = [super initWithFrame:frame];
    if(self){
       
        self.backView = [[UIView alloc]initWithFrame:self.bounds];
        self.backView.backgroundColor = [UIColor blackColor];
        
        [self addSubview:self.backView];
        
        
        self.contentView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, ContentWidth, ContentHeight)];
        self.contentView.backgroundColor = [UIColor whiteColor];
        self.contentView.layer.cornerRadius = 8.0f;
        self.contentView.center = self.center;
        [self addSubview:self.contentView];
        
        
        self.backImg = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"WechatIMG"]];
        self.frontImg = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"WechatIMG"]];
        
        self.backImg.frame = CGRectMake(Margin, Margin, ContentWidth-Margin*2, ContentWidth-Margin*2);
        self.frontImg.frame = CGRectMake(Margin, Margin, ContentWidth-Margin*2, ContentWidth-Margin*2);
        [self.contentView addSubview:self.backImg];
        [self.contentView addSubview:self.frontImg];
        
        self.progressView = [[CustomProgressView alloc]initWithFrame:CGRectMake(Margin, CGRectGetMaxY(self.backImg.frame)+Margin, ContentWidth-Margin*2, Margin*2)];
        [self.contentView addSubview:self.progressView];
        __block typeof(self)weakSelf = self;
        self.progressView.blockProgressValue = ^(float value,BOOL isEnd) {
            if(isEnd){
                //这个地方判断5只是为了给滑动的图片一个容错性,偏离5个像素也判断是对的
                CGRect frontRect = weakSelf.frontImg.frame;
                CGRect backRect = weakSelf.backImg.frame;
                if(frontRect.origin.x-backRect.origin.x < 5 && frontRect.origin.x-backRect.origin.x > -5){
                    //成功了移除
                    [weakSelf hidden];
                }else{
                    //失败了刷新继续拼图
                   
                    [weakSelf refreshView];
                }
               
            }else{
                float width = frame.size.width * value;
                CGRect rect = weakSelf.frontImg.frame;
                rect.origin.x = self->frontRect.origin.x+width;
                
                weakSelf.frontImg.frame = rect;
            }
           
        };

        
        [self refreshView];
        
    }
    return self;
}
/**
 刷新当前界面
 */
-(void)refreshView{
    //刷新的时候progressView的值为0,设置到原始值
     [self.progressView setProgress:0];
    //如果self.backImg上有上次停留的Layer,则删除
    for(CALayer *layer in [self.backImg.layer sublayers]){
        [layer removeFromSuperlayer];
    }
    
    int width = self.backImg.frame.size.width - 40;
    //x-50的原因以及height-40是不想让模块出现在边框之外
    int x = arc4random() % width ;
    if(x < 50){
        x = 50;
    }
    int height = self.backImg.frame.size.height - 40;
    int y = arc4random() % height;
    CAShapeLayer *shapeLayer = [CAShapeLayer layer];
    shapeLayer.path = [self getPath].CGPath;
    [shapeLayer setFillColor:[UIColor whiteColor].CGColor];
    shapeLayer.frame = CGRectMake(x, y, 36, 36);
    [self.backImg.layer addSublayer:shapeLayer];
    //-x+Margin是因为backImg前面有Margin个空白间距
    frontRect = CGRectMake(-x+Margin, self.backImg.frame.origin.y, self.backImg.frame.size.width, self.backImg.frame.size.height);
    self.frontImg.frame = frontRect;
    UIBezierPath *path = [self getPath];
    CGAffineTransform transform = CGAffineTransformMakeTranslation(x, y);
    [path applyTransform: transform];
    CAShapeLayer *maskLayer = [CAShapeLayer layer];
    maskLayer.path = path.CGPath;

    self.frontImg.layer.mask = maskLayer;
}

-(void)show{
    UIWindow *window = [[UIApplication sharedApplication]keyWindow];
    [window addSubview:self];
    __block typeof(self)weakSelf = self;
    [UIView animateWithDuration:.5f animations:^{
        weakSelf.backView.alpha = .3f;
    }];
}
-(void)hidden{
    __block typeof(self)weakSelf = self;
    [UIView animateWithDuration:.5f animations:^{
        CGRect rect = weakSelf.frame;
        rect.size.height = 0;
        weakSelf.frame = rect;
        weakSelf.alpha = 0;
    } completion:^(BOOL finished) {
        [weakSelf removeFromSuperview];
    }];
}


//画蒙版的形状
-(UIBezierPath *)getPath{
    UIBezierPath * path = [UIBezierPath bezierPath];
    [path moveToPoint:CGPointMake(0.f, 4.0f)];
    [path addLineToPoint:CGPointMake(12.f, 4.0f)];
    [path addArcWithCenter:CGPointMake(16.f,4.0f) radius:4.0 startAngle:M_PI endAngle:2*M_PI clockwise:YES];
    [path addLineToPoint:CGPointMake(32.f, 4.0f)];
    [path addLineToPoint:CGPointMake(32.f, 12.f)];
    [path addArcWithCenter:CGPointMake(32.f,20.f) radius:4.0 startAngle:1.5*M_PI endAngle:2.5*M_PI clockwise:YES];
    [path addLineToPoint:CGPointMake(32.f, 36.f)];
    [path addLineToPoint:CGPointMake(24.f, 36.f)];
    [path addArcWithCenter:CGPointMake(16.f,36.f) radius:4.0 startAngle:2*M_PI endAngle:M_PI clockwise:NO];
    [path addLineToPoint:CGPointMake(0.f, 36.f)];
    [path addLineToPoint:CGPointMake(0.f, 28.f)];
    [path addArcWithCenter:CGPointMake(0.f,20.f) radius:4.0 startAngle:2.5*M_PI endAngle:1.5*M_PI clockwise:NO];
    [path closePath];
    return path;
}
@end

 使用

 

posted @ 2018-12-07 09:48  新年新气象  阅读(417)  评论(0编辑  收藏  举报