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
使用
OC图片滑动验证的更多相关文章
- 滑动验证 和滑动图片验证JS
滑动验证 先放效果图 <!DOCTYPE html> <html lang="en"> <head> <meta charset=&quo ...
- Python实现图片滑动式验证识别
1 abstract 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手.很多已经做案例的人,却不知道如何去学习更加高深的知识.那么针对这三类 ...
- 滑动验证的设计与实现J2EE
滑动验证的设计与实现J2EE 注:本博文为博主原创,转载请注明出处. 项目源码地址:https://github.com/zhangxy1035/Verify 本篇博文的主要目录如下: 一.项目简介二 ...
- C# Selenium 破解腾讯滑动验证
什么是Selenium? WebDriver是主流Web应用自动化测试框架,具有清晰面向对象 API,能以最佳的方式与浏览器进行交互. 支持的浏览器: Mozilla Firefox Google C ...
- [Android实例] 拖动滑块进行图片拼合验证方式的实现
该篇文章从eoeAndroid搬迁过来的,原文地址:[Android实例] 拖动滑块进行图片拼合验证方式的实现 现在网站上有各种各样的验证码验证方式,比如计算大小,输入图片内容等,今天在一家网站上看到 ...
- vue 图片滑动登录
前言 最近在研究图片滑动解锁 登录,说是要用阿里的那个验证,但是还是想自己手写下这个Demo 效果图是这样的: 本来是想用canvas 来实现的,但是类,后来还想用css 和图片来代替canvas 其 ...
- What?废柴, 模拟登陆,代码控制滑动验证真的很难吗?Are you kidding???
1.简介 在前边的python接口自动化的时候,我们由于博客园的登录机制的改变,没有用博客园的登录测试接口.那么博客园现在变成了滑动验证登录,而且现在绝大多数的登录都变成这种滑动验证和验证码的登录验证 ...
- uni-app开发经验分享二十一: 图片滑动解锁插件制作解析
在开发用户模块的时候,相信大家都碰到过一个功能,图片滑动解锁后发送验证码,这里分享我用uni-app制作的一个小控件 效果如下: 需要如下图片资源 template <template> ...
- javascript效果:手风琴、轮播图、图片滑动
最近都没有更,就来几个效果充实一下. 都没有进行美化这步. 手风琴: 纯css: <!DOCTYPE html> <html lang="en"> < ...
随机推荐
- 和我一起学Effective Java之泛型
泛型 不要在新代码中使用原始类型 泛型(generic):声明中具有一个或多个类型参数 原始类型(raw type):不带任何实际类型参数的泛型名称 格式: 类或接口的名称 < 对应于泛型形式类 ...
- 设计模式-行为型模式,python访问者模式
访问者模式 在访问者模式(Visitor Pattern)中,我们使用了一个访问者类,它改变了元素类的执行算法.通过这种方式,元素的执行算法可以随着访问者改变而改变.这种类型的设计模式属于行为型模式. ...
- [Artoolkit] Android Sample of nftSimple
结合:[Artoolkit] ARToolKit's SDK Structure on Android 重难点:aRBaseLib/, nftSimple/, libcpufeatures.a aRB ...
- [Laravel] 08 - Auth & Data Migration
登录注册框架 一.加载Auth模块 Step 1, 安装Auth模块 生成相关 laravel 框架内部的代码模块: $ php artisan make:auth 自动添加了路由代码 在larave ...
- cocos2dx内存管理
cocos2dx基于引用计数管理内存,所有继承自CCObject的对象都将获得引用计数的能力,可通过调用retain成员函数用于引用计数值,调用release减少引用计数值,当计数值减为0时销毁对象. ...
- 正则表达式/(^\s*)|(\s*$)/g意思
包含以空格.回车符等字符开头 或者 空格.回车符等字符结尾 的字符串,可过滤出所有空格.回车符的字符
- linux如何安装多个jdk?
1 官网下载JDK版本 jdk-8u181-linux-x64.tar.gz 2 利用ssh工具上传安装包到Linux系统 传至:/usr/local 3 Linux用户安装的程序一般放在 /usr/ ...
- F - Rails
There is a famous railway station in PopPush City. Country there is incredibly hilly. The station wa ...
- 三剑客之awk
简介 awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大.简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再 ...
- xshell连接Linux、ngix部署
Linux端安装sshd服务(openssh-server) 查看防火墙:ufw(Linux默认安装了) 再就是客户端了.. 平时在测试环境下的项目不能承载高并发,需要部署到web server上.w ...