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"> < ...
随机推荐
- python web自动化测试中失败截图方法汇总
在使用web自动化测试中,用例失败则自动截图的网上也有,但实际能落地的却没看到,现总结在在实际应用中失败截图的几种方法: 一.使用unittest框架截图方法: 1.在tearDown中写入截图的 ...
- 10.5ORM回顾(2)
2018-10-5 14:47:57 越努力越幸运!永远不要高估自己! ORM的聚合和分组查询!!! # #####################聚合和分组##################### ...
- 错误票据|2013年蓝桥杯B组题解析第七题-fishers
错误票据 某涉密单位下发了某种票据,并要在年终全部收回. 因为工作人员疏忽,在录入ID号的时候发生了一处错误,造成了某个ID断号,另外一个ID重号. 你的任务是通过编程,找出断号的ID和重号的ID. ...
- 二进制安装mysql
1.1 MySQL安装介绍 mysql软件下载地址信息: www.mysql.com mirrors.sohu.com mysql软件下载完毕后,查看mysql解压后目录文件大小 1.下载解压my ...
- C++设计实现一个不能被继承的类
C++不同于Java,Java中被final关键字修饰的类不能被继承,C++能实现不被继承的类,但是需要自己实现. 为了使类不被继承,最好的办法是使子类不能构造父类的部分,此时子类就无法实例化整个子类 ...
- .NET Core错误:The specified framework 'Microsoft.NETCore.App', version '1.0.0-rc2-3002702' was not found.
本地Dos命令行中,cd到你的项目目录下,生成, dotnet {U_Project_Name}.dll 发布 dotnet publish ,然后将发布的文件夹中的文件全部拷贝到服务器中,至此,问题 ...
- [No0000100]正则表达式匹配解析过程分析(正则表达式匹配原理)&regexbuddy使用&正则优化
常见正则表达式引擎引擎决定了正则表达式匹配方法及内部搜索过程,了解它至关重要的.目前主要流行引擎有:DFA,NFA两种引擎. 引擎 区别点 DFA Deterministic finite autom ...
- [No0000CB]如何在命令行(cmd)通过TCP/IP端口(port)查询所在的进程号(pid)或进程名称,并终止该进程
1)首先查找占用某个端口的进程PID netstat -ano | findstr [port] 2)根据该进程pid查询进程名称或标题,确认那个程序在占用该端口 tasklist /v | fi ...
- HTML5:表单提交
不加CSS.JavaScrips的HTML表单提交简单代码 <!DOCTYPE html> <html lang="en"> <head> &l ...
- git commit -m 与 git commit -am的区别
字面解释的话,git commit -m用于提交暂存区的文件:git commit -am用于提交跟踪过的文件 要理解它们的区别,首先要明白git的文件状态变化周期,如下图所示 工作目录下面的所有文件 ...